Using sed to mass rename files
First, I should say that the easiest way to do this is to use theprename or rename commands.
On Ubuntu, OSX (Homebrew package rename
, MacPorts package p5-file-rename
), or other systems with perl rename (prename):
rename s/0000/000/ F0000*
or on systems with rename from util-linux-ng, such as RHEL:
rename 0000 000 F0000*
That's a lot more understandable than the equivalent sed command.
But as for understanding the sed command, the sed manpage is helpful. Ifyou run man sed and search for & (using the / command to search),you'll find it's a special character in s/foo/bar/ replacements.
s/regexp/replacement/ Attempt to match regexp against the pattern space. If successâ ful, replace that portion matched with replacement. The replacement may contain the special character & to refer to that portion of the pattern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.
Therefore, \(.\)
matches the first character, which can be referenced by \1
.Then .
matches the next character, which is always 0.Then \(.*\)
matches the rest of the filename, which can be referenced by \2
.
The replacement string puts it all together using &
(the originalfilename) and \1\2
which is every part of the filename except the 2ndcharacter, which was a 0.
This is a pretty cryptic way to do this, IMHO. If forsome reason the rename command was not available and you wanted to usesed to do the rename (or perhaps you were doing something too complexfor rename?), being more explicit in your regex would make it muchmore readable. Perhaps something like:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
Being able to see what's actually changing in thes/search/replacement/ makes it much more readable. Also it won't keepsucking characters out of your filename if you accidentally run ittwice or something.
you've had your sed explanation, now you can use just the shell, no need external commands
for file in F0000*do echo mv "$file" "${file/#F0000/F000}" # ${file/#F0000/F000} means replace the pattern that starts at beginning of stringdone
I wrote a small post with examples on batch renaming using sed
couple of years ago:
http://www.guyrutenberg.com/2009/01/12/batch-renaming-using-sed/
For example:
for i in *; do mv "$i" "`echo $i | sed "s/regex/replace_text/"`";done
If the regex contains groups (e.g. \(subregex\
) then you can use them in the replacement text as \1\
,\2
etc.