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


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
    rename [switches|transforms] [files]


    -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)
    -l/--symlink or -L/--hardlink

    Transforms, applied sequentially:

    -s/--subst *from* *to*
    -S/--subst-all *from* *to*
    --camelcase --urlesc --nows --rews --noctrl --nometa --trim (see manual)

5 Answers 5


Try with this:

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


$ 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, 2017 at 21:20
  • 1
    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, 2017 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. Feb 22, 2017 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, 2017 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, 2017 at 14:04

With the version of rename that you seem to be using, the following expression should do the transformation you request (example 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.


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]

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.

  • This is the best answer adjustable to however many files need to be renamed. Nov 9, 2019 at 18:23
  • Although I am getting an Anomalous backslash in string: '\g'. String constant might be missing an r prefix. (anomalous-backslash-in-string) error Nov 9, 2019 at 18:39
  • could not run it so I chmod 755'd it. and now getting a boat load of errors:import-im6.q16: not authorized sys' @ error/constitute.c/WriteImage/1037. import-im6.q16: not authorized os' @ error/constitute.c/WriteImage/1037. import-im6.q16: not authorized re' @ error/constitute.c/WriteImage/1037. ./renameLeadZero.py: line 6: syntax error near unexpected token if' ./renameLeadZero.py: line 6: if file in file: continue' ` I am using a conda env so probably have to designate the interpreter on the shebang differently? Nov 9, 2019 at 18:52
  • 1
    @mLstudent33 That's peculiar. The error in your second comment probably stems from a backslash in one of the filenames. Python regex thinks it's a special backslash escape. We probably can get around that by adding repr() around file in re.split() line, or string formatting ( stackoverflow.com/q/18707338/3701431 ) but we'll need to take into account whether it's Python3 or Python2.7 we have on the system - their string formatting is different just a bit. For the error in the third comment, I cannot confirm nor deny - never worked with Conda. Nov 9, 2019 at 19:49
  • Thanks for the reply. Nov 9, 2019 at 19:52

I have done with ls + awk + sh for the sake of challenge:

ls -1 | awk -F_ '{printf "%s%02d.jpg\n", "mv "$0" "$1"_"$2"_", $3}' | sh

-F_ ............... field separator
%s ................ string to "mv "$0" "$1"_"$2"_"
%02d .............. our numeric field with leading zeros

To just see the command with no modifications remove the | sh

  • In general, providing commands in plain text to sh, after processing unknown filenames, is vulnerable to code injection. Think of a file named 1 2;rm -rf ~;_Ex_1.jpg.
    – thanasisp
    Nov 15, 2020 at 14:34
  • 1
    For sure thanasisp, but as I have said we can see the command before runing it simply by removing the | sh. Nov 15, 2020 at 15:18

One answer above gives:

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

However, that gives incorrect results for me, since *.jpg sorts the files in strict numerical order. Running rename with the -n flag for a dry run gives me:

rename(9999.jpg, frames_0000039996.jpg) 
rename(999.jpg, frames_0000039997.jpg) 
rename(99.jpg, frames_0000039998.jpg) 
rename(9.jpg, frames_0000039999.jpg)

Correct results can be had with:

rename 's/.+/our $i; sprintf("frames_%010d.jpg", 0+$i++)/e' $(ls -1 | sort -V)

which gives

rename(9999.jpg, frames_0000039996.jpg)
rename(999.jpg, frames_0000039997.jpg)
rename(99.jpg, frames_0000039998.jpg)
rename(9.jpg, frames_0000039999.jpg)

with the -n flag.

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.