7

I've tried a bunch of examples of the rename command but I can't figure out the syntax to do what I want.

I have a bunch of files labeled something like

File_Ex_1.jpg
File_Ex_2.jpg
File_Ex_3.jpg
File_Ex_4.jpg
...
File_Ex_10.jpg
File_Ex_11.jpg
etc. 

I want to change only some of them by inserting a 0 so that the file names have the same number of characters.

So I want File_Ex_1.jpg to go to File_Ex_01.jpg, File_Ex_2.jpg to File_Ex_02.jpg

How do you do this with the rename command?

This rename command was installed via home-brew on a Mac. Output of rename -v:

rename -v
Usage:
    rename [switches|transforms] [files]

    Switches:

    -0/--null (when reading from STDIN)
    -f/--force or -i/--interactive (proceed or prompt when overwriting)
Wide character in print at /System/Library/Perl/5.18/Pod/Text.pm line 286.

    -g/--glob (expand "*" etc. in filenames, useful in Windows™ CMD.EXE)
    -k/--backwards/--reverse-order
    -l/--symlink or -L/--hardlink
    -M/--use=*Module*
    -n/--just-print/--dry-run
    -N/--counter-format
    -p/--mkpath/--make-dirs
    --stdin/--no-stdin
    -t/--sort-time
    -T/--transcode=*encoding*
    -v/--verbose

    Transforms, applied sequentially:

    -a/--append=*str*
    -A/--prepend=*str*
    -c/--lower-case
    -C/--upper-case
    -d/--delete=*str*
    -D/--delete-all=*str*
    -e/--expr=*code*
    -P/--pipe=*cmd*
    -s/--subst *from* *to*
    -S/--subst-all *from* *to*
    -x/--remove-extension
    -X/--keep-extension
    -z/--sanitize
    --camelcase --urlesc --nows --rews --noctrl --nometa --trim (see manual)
11

Try with this:

rename -e 's/\d+/sprintf("%02d",$&)/e' -- *.jpg

Example:

$ ls
Device_Ex_10.jpg  Device_Ex_1.jpg  Device_Ex_4.jpg  Device_Ex_7.jpg
Device_Ex_11.jpg  Device_Ex_2.jpg  Device_Ex_5.jpg  Device_Ex_8.jpg
Device_Ex_12.jpg  Device_Ex_3.jpg  Device_Ex_6.jpg  Device_Ex_9.jpg
$ rename -e 's/\d+/sprintf("%02d",$&)/e' -- *.jpg
$ ls
Device_Ex_01.jpg  Device_Ex_04.jpg  Device_Ex_07.jpg  Device_Ex_10.jpg
Device_Ex_02.jpg  Device_Ex_05.jpg  Device_Ex_08.jpg  Device_Ex_11.jpg
Device_Ex_03.jpg  Device_Ex_06.jpg  Device_Ex_09.jpg  Device_Ex_12.jpg

I took the reference from here: https://stackoverflow.com/questions/5417979/batch-rename-sequential-files-by-padding-with-zeroes

Here adapted to your particular rename implementation.

  • This looks like a proper call for the Perl-based version of rename, which the asker doesn't appear to have. – dhag Feb 22 '17 at 21:20
  • Is there a good reference to explain what these commands mean? Like what the + sign does. This is close, except I guess the real format for my filenames is Device1_Ex_1.jpg Where this syntax would turn that into Device01_Ex_1.jpg and not Device1_Ex_01.jpg – toombzie Feb 22 '17 at 21:21
  • 1
    @dhag The asker definitely has a Perl-based version, both because they aren't running Linux so they don't have the util-linux rename, and because the output of rename -v explicitly mentions Perl. – Gilles Feb 22 '17 at 22:24
  • 1
    Yes, OK, my wording was terrible. I should have said "the version that accepts a Perl expression as one of its parameters". This still looks like a wrong answer, doesn't it? – dhag Feb 22 '17 at 22:44
  • Interestingly, while this appears to contradict the help text which, if I understand correctly, requires -e before the Perl code, this call actually works with the rename utility that comes with macOS. I retract my initial comment. – dhag Feb 23 '17 at 14:04
2

With the version of rename that you seem to be using, the following expression should do the transformation you request (exammple with a directory containing files named File_Ex_{1..11}.jpg):

$ rename -n -e 's/_(\d\.)/_0$1/g' -- *.jpg
'File_Ex_1.jpg' would be renamed to 'File_Ex_01.jpg'
'File_Ex_2.jpg' would be renamed to 'File_Ex_02.jpg'
'File_Ex_3.jpg' would be renamed to 'File_Ex_03.jpg'
'File_Ex_4.jpg' would be renamed to 'File_Ex_04.jpg'
'File_Ex_5.jpg' would be renamed to 'File_Ex_05.jpg'
'File_Ex_6.jpg' would be renamed to 'File_Ex_06.jpg'
'File_Ex_7.jpg' would be renamed to 'File_Ex_07.jpg'
'File_Ex_8.jpg' would be renamed to 'File_Ex_08.jpg'
'File_Ex_9.jpg' would be renamed to 'File_Ex_09.jpg'

(Remove flag -n to actually do the renaming.)

The argument to -e is a Perl search-and-replace expression; where _(\d\.) matches am underscore followed by a single digit and then a dot, and replaces the underscore with _0, thus inserting a leading zero. $1 is a back-reference to the group within parentheses, the digit and dot, and leaves it unchanged in the new file name.

0

While it can be done with prename command, I would like to provide a python alternative to that:

$ ls
File_Ex_1.jpg  File_Ex_2.jpg  File_Ex_3.jpg  File_Ex_4.jpg

$ ./pad_zeros.py *                                                                                                       

$ ls
File_Ex_01.jpg  File_Ex_02.jpg  File_Ex_03.jpg  File_Ex_04.jpg  pad_zeros.py*

The pad_zeros.py script is simple:

#!/usr/bin/env python
import sys,os,re

for file in sys.argv[1:]:
    if __file__ in file: continue
    words = re.split('_|\.',file)
    words[-2] = words[-2].zfill(2)
    new_name = "_".join(words[:-1]) + "." + words[-1]
    os.rename(file,new_name)

It takes arguments on command-line, iterates over them, and pads zeros using .zfill() command(in this particular case to two characters). Since we're operating on all files in the same folder, glob-star can be used.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.