Renaming a file extension without specifying
I am creating a bash shell script that will rename a file extension without having to specify the old file extension name. If I enter "change foo *" to the Terminal in Linux, it will change all file extension to foo.
So lets say I've got four files: "file1.txt", "file2.txt.txt", "file3.txt.txt.txt" and "file4."
When I run the command, the files should look like this: "file1.foo", "file2.txt.foo", "file3.txt.txt.foo" and "fi开发者_如何学Pythonle4.foo"
Can someone look at my code and correct it. I would also appreciate it if someone can implement this for me.
#!/bin/bash
shift
ext=$1
for file in "$@"
do
cut=`echo $FILE |sed -n '/^[a-Z0-9]*\./p'`
if test "${cut}X" == 'X'; then
new="$file.$ext"
else
new=`echo $file | sed "s/\(.*\)\..*/\1.$ext/"`
fi
mv $file $new
done
exit
- Always use double quotes around variable substitutions, e.g.
echo "$FILE"
and notecho $FILE
. Without double quotes, the shell expands whitespace and glob characters (\[*?
) in the value of the variable. (There are cases where you don't need the quotes, and sometimes you do want word splitting, but that's for a future lesson.) - I'm not sure what you're trying to do with sed, but whatever it is, I'm sure it's doable in the shell.
- To check if
$FILE
contains a dot:case "$FILE" in *.*) echo yes;; *) echo no;; esac
- To strip the last extension from
$FILE
:${FILE%.*}
. For example, if$FILE
isfile1.txt.foo
, this producesfile1.txt
. More generally,${FILE%SOME_PATTERN}
expands to$FILE
with a the shortest suffix matchingSOME_PATTERN
stripped off. If there is no matching suffix, it expands to$FILE
unchanged. The variant${FILE%%SOME_PATTERN}
strips the longest suffix. Similarly,${FILE#SOME_PATTERN}
and${FILE##SOME_PATTERN}
strip a suffix.
- To check if
test "${TEMP}X" == 'X'
is weird. This looks like a misremembered trick from the old days. The normal way of writing this is[ "$TEMP" = "" ]
or[ -z "$TEMP" ]
. Using==
instead of=
is a bash extension. There used to be buggy shells that might parse the command incorrectly if$TEMP
looked like an operator, but these have gone the way of the dinosaur, and even then, theX
needs to be at the beginning, because the problematic operators begin with a-
:[ "X$TEMP" == "X" ]
.- If a file name begins with a
-
,mv
will think it's an option. Use--
to say “that's it, no more options, whatever follows is an operand”:mv -- "$FILE" "$NEW_FILE"
. - This is very minor, but a common (not universal) convention is to use capital letters for environment variables and lowercase letters for internal script variables.
- Since you're using only standard shell features, you can start the script with
#!/bin/sh
(but#!/bin/bash
works too, of course). exit
at the end of the script is useless.
Applying all of these, here's the resulting script.
#!/bin/sh
ext="$1"; shift
for file in "$@"; do
base="${file%.*}"
mv -- "$file" "$base.$ext"
done
Not exactly what you are asking about, but have a look at the perl rename
utility. Very powerful! man rename
is a good start.
Use: for file in *.gif; do mv $file ${file%.gif}.jpg; done
Or see How to rename multiple files
For me this worked
for FILE in `ls`
do
NEW_FILE=${FILE%.*}
NEW_FILE=${NEW_FILE}${EXT}
done
I just want to tell about NEW_FILE=${FILE%.*}
.
Here NEW_FILE gets the file name as output. You can use it as you want.
I tested in bash with uname -a = "Linux 2.4.20-8smp #1 SMP Thu Mar 13 17:45:54 EST 2003 i686 i686 i386 GNU/Linux"
精彩评论