Renaming files like a pro

Renaming files en masse was always something that I knew the commandline could excel at but that I'd never managed to easily replicate daily. I'd always have to look up the shell syntax for looping over a list of files, and the rules for escaping paths, and so on and so forth. Whilst I'd like to improve my skills with the shell, in the meantime I have discovered another option, rename.

Now, when I say rename, there is some confusion about various different versions of this utility. I've been using the version included with Ubuntu Trusty 14.04 and also the version included in Homebrew on macOS Sierra. The examples below work with both of these versions.

A good understanding of regular expressions (the Perl variety) will allow you to get the most out of rename but you can still use it in a basic fashion and get great results.

Some examples

Take these files.

1
2
3
01-run_the_jewels-run_the_jewels.flac
02-run_the_jewels-banana_clipper_(feat._big_boi).flac
03-run_the_jewels-36_inch_chain.flac

Let's make the filenames uppercase (because we are monsters).

1
2
3
4
$ rename -n 'y/a-z/A-Z/ *.flac
01-run_the_jewels-run_the_jewels.flac renamed as 01-RUN_THE_JEWELS-RUN_THE_JEWELS.FLAC
02-run_the_jewels-banana_clipper_(feat._big_boi).flac renamed as 02-RUN_THE_JEWELS-BANANA_CLIPPER_(FEAT._BIG_BOI).FLAC
03-run_the_jewels-36_inch_chain.flac renamed as 03-RUN_THE_JEWELS-36_INCH_CHAIN.FLAC

You'll notice that rename prints out the renaming it would do. This is because we've used the -n flag, which turns on dry runs allowing us to see the changes that will be made before we commit to changing them. You'll find -n invaluable when using rename, especially when new to it.

Let's change dashes and underscores to spaces instead.

1
2
3
4
$ rename -n 's/-|_/ /g' *.flac
'01-run_the_jewels-run_the_jewels.flac' would be renamed to '01 run the jewels run the jewels.flac'
'02-run_the_jewels-banana_clipper_(feat._big_boi).flac' would be renamed to '02 run the jewels banana clipper (feat. big boi).flac'
'03-run_the_jewels-36_inch_chain.flac' would be renamed to '03 run the jewels 36 inch chain.flac'

Or remove -run_the_jewels- from the filename entirely.

1
2
3
4
$ rename -n 's/-run_the_jewels-/ /g' *.flac
'01-run_the_jewels-run_the_jewels.flac' would be renamed to '01 run_the_jewels.flac'
'02-run_the_jewels-banana_clipper_(feat._big_boi).flac' would be renamed to '02 banana_clipper_(feat._big_boi).flac'
'03-run_the_jewels-36_inch_chain.flac' would be renamed to '03 36_inch_chain.flac'

Getting a bit more advanced, you can even use captures in your expression. Take a directory of files with names like this.

1
2
3
S03E01-oh-em-gee-i-love-telly.mkv
S03E02-thrilling-watch.mkv
S03E03-a-great-episode.mkv

We'll rename the filenames to look like S??E??.mkv.

1
2
3
4
$ rename -n 's/.*(S\d{1,2}E\d{1,2}).*(.{3}$)/$1.$2/g' *.mkv
'S03E01-oh-em-gee-i-love-telly.mkv' would be renamed to 'S03E01.mkv'
'S03E02-thrilling-watch.mkv' would be renamed to 'S03E02.mkv'
'S03E03-a-great-episode.mkv' would be renamed to 'S03E03.mkv'

The regular expression matches the S??E?? part of the filename as $1, and the extension .mkv as $2, and uses them both to construct a new filename like S03E01.mkv.

That regular expression is quite a mouthfull, so I'd recommend using a tool to help you construct your expressions. I personally use Rubular even though it's Ruby-specific; it does a good job for me.

I hope you can get a sense of how powerful rename can be. Regular expressions are the limit to how you can rename files.