The rename perl script is pretty great. Immensely powerful, buuut not the most intuitive. If you are not the most proficient in perl, you may find yourself trying several times to get something working just like you want. Of course by the next time you need that particular functionality, you forgot all about how to do it and have to look for the solution again. Doing the obvious, I figure I should keep track of some of them. Ideally, I will be updating this post as I find others. To really understand what is happening here, you will need knowledge of regular expressions though. (The perl kind, not the computer science one)

Special Characters

  • $&: the match
  • $\: the text before the match
  • $': the text after the match
  • $1, $2, $3, …: the first, second, third, … backreferenced match (those with parentheses around them)
  • @{[ perl_code() ]}: runs that part of the replacement string through the Perl interpreter
  • e flag: runs entire replacement string through the Perl interpreter

Adding leading zeros

rename 's/\d+/sprintf("%05d", $&)/e' *

This assumes there is only one number in the filenames you are renaming. It matches against the number and uses perl’s sprintf to add leading zeros. In the example’s case the number is zero filled such that there are 5 digits total.

Note the e flag here, it runs the entire replacement string through the Perl interpreter.

Adding File Modification Date

Via Oli on AskUbuntu.

rename 's/(\d+\.jpg)/use File::stat; sprintf("%s-%s", stat($&)->mtime, $1)/e' * -v

Add the time in seconds since the Unix Epoch to the start of the filename. Note here it is specifically looking for a match of digits and a .jpg extension.

rename 's/(\d+\.jpg)/use File::stat; use POSIX; sprintf("%s-%s", strftime("%Y%m%d-%H%M%S", localtime(stat($&)->mtime)), $1)/e' * -v

Add the time in %Y%m%d-%H%M%S format to the start of the filename.

Adding File Creation Date With Exiftool

Some formats, like image formats, might have metadata available that serves itself better to be used by means of exiftool. The following examples and explanation are straight from the exiftool manual.

exiftool '-FileName<CreateDate' -d %Y%m%d_%H%M%S%%-c.%%e dir

Rename all images in dir according to the CreateDate date and time, adding a copy number with leading ‘-‘ if the file already exists (%-c), and preserving the original file extension (%e). Note the extra % necessary to escape the filename codes (%c and %e) in the date format string.

exiftool -r '-FileName<CreateDate' -d %Y-%m-%d/%H%M_%%f.%%e dir

Both the directory and the filename may be changed together via the FileName tag if the new FileName contains a /. The example above recursively renames all images in a directory by adding a CreateDate timestamp to the start of the filename, then moves them into new directories named by date.

exiftool '-FileName<${CreateDate}_$filenumber.jpg' -d %Y%m%d *.jpg

Set the filename of all JPG images in the current directory from the CreateDate and FileNumber tags, in the form “20060507_118-1861.jpg”.

Subtraction on the Replacement Side

In reality this also just enables any sort of Perl evaluation. There is the option of using the e flag at the end (like in the leading zero example). However, this turns your entire replacement string into code that will be evaluated by Perl. If instead you want to keep it simple and throw just a part through the evaluator, you can use the following to embed some Perl code.

@{[ perl_code() ]}

For the sake of the example, suppose you have pictures with sequential numbering starting at 100. You can make the numbering start at 1 instead with this

rename -n 's/Photo(\d\d)/Photo@{[ $1 - 99 ]}/' *

Note I used the -n flag to ensure you do not just execute it willy-nilly. Check the output, then remove the -n to actually execute it. If you want leading zeroes, you can combine it with the earlier example.

rename -n 's/Photo(\d\d)/Photo@{[ sprintf("%03d", $1 - 99) ]}/' *