Rename scripts
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 interpretere
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) ]}/' *