Batch Renaming Using sed

I was reorganizing my music library and decided to change the naming convention I’d used. This task was just asking to be automated. Since the filename change could be described using a regular expression, I looked for a way to use sed for the renaming process.

The files I had followed the filename pattern ARTIST – SONG – TRACK – ALBUM

James Brown - I Got You (I Feel Good).ogg  - 01 - Classic James Brown

I wanted to rename them to ARTIST – ALBUM – TRACK – NAME

James Brown - Classic James Brown - 01 - I Got You (I Feel Good).ogg

Describing the change as a sed program is easy:

s/(.*) - (.*) - (.*) - (.*).ogg/1 - 4 - 3 - 2.ogg/

Now all that has to be done is to pass each filename to mv and pass it again after it has gone through the sed script. This can be done like this:

for i in *; do
  mv "$i" "`echo $i | sed "s/(.*) - (.*) - (.*) - (.*).ogg/1 - 4 - 3 - 2.ogg/"`";
done

The important part is

`echo $i | sed "s/(.*) - (.*) - (.*) - (.*).ogg/1 - 4 - 3 - 2.ogg/"`

which pipes the filename to sed and returns it as an argument for mv.

To see what renaming will be done, one can alter the above command a bit and get

for i in *; do
  echo "$i" "->" "`echo $i | sed "s/(.*) - (.*) - (.*) - (.*).ogg/1 - 4 - 3 - 2.ogg/"`";
done

which will effectively print a list of lines in the form oldname -> newname.

Of course, this technique isn’t limited to the renaming I’ve done. By changing the pattern given to sed, one can do any kind of renaming that can be described as a regular expression replacement. Also, one can change the globbing (the *) in the for loop to operate only on specific files that match a given pattern in the directory, instead of all of them.