Changing file extensions with sed [duplicate]

2019-07-17 04:46发布

问题:

This question already has an answer here:

  • How to use sed to change file extensions? 6 answers

If the arguments are files, I want to change their extensions to .file.

That's what I got:

#!/bin/bash

while [ $# -gt 0 ]
do
    if [ -f $1 ]
    then
       sed -i -e "s/\(.*\)\(\.\)\(.*\)/\1\2file" $1

    fi
    shift
done

The script is running, but it doesn't do anything. Another problem is that file hasn't any extension, my sed command will not work, right? Please help.

回答1:

sed is for manipulating the contents of files, not the filename itself.

Option 1, taken from this answer by John Smith:

filename="file.ext1"
mv "${filename}" "${filename/%ext1/ext2}"

Option 2, taken from this answer by chooban:

rename 's/\.ext/\.newext/' ./*.ext

Option 3, taken from this answer by David W.:

$ find . -name "*.ext1" -print0 | while read -d $'\0' file
do
   mv $file "${file%.*}.ext2"
done

and more is here.

UPDATE : (in comment asked what % and {} doing?)

"${variable}othter_chars" > if you want expand a variable in string you can use it. and %.* in {} means take the value of variable strip off the pattern .* from the tail of the value for example if your variable be filename.txt "${variable%.*} return just filename.



回答2:

Using a shell function to wrap a sed evaluate (e) command:

mvext () 
{ 
    ext="$1";
    while shift && [ "$1" ]; do
        sed 's/.*/mv -iv "&" "&/
             s/\(.*\)\.[^.]*$/\1/
             s/.*/&\.'"${ext}"'"/e' <<< "$1";
    done
}

Tests, given files bah and boo, and the extension should be .file, which is then changed to .buzz:

 mvext file bah boo
 mvext buzz b*.file

Output:

'bah' -> 'bah.file'
'boo' -> 'boo.file'
'bah.file' -> 'bah.buzz'
'boo.file' -> 'boo.buzz'

How it works:

  1. The first arg is the file extension, which is stored in $ext.
  2. The while loop parses each file name separately, since a name might include escaped spaces and whatnot. If the filenames were certain to have not such escaped spaces, the while loop could probably be avoided.
  3. sed reads standard input, provided by a bash here string <<< "$1".
  4. The sed code changes each name foo.bar (or even just plain foo) to the string "mv -iv foo.bar foo.file" then runs that string with the evaluate command. The -iv options show what's been moved and prompts if an existing file might be overwritten.