I've got a bunch of numbered files like this:

file #01.ext
file #02.ext
file #03.ext
file #04.ext
file #05.ext

And what I want is to make them all have three digits (two leading 0's) instead of one, so;

file #001.ext
file #002.ext
file #003.ext
file #004.ext
file #005.ext

My thought is to use sed to replace the # with #0 (which in my case is good enough, there are no files over #99 yet). All the files are in the same folder, how would I do that?

4 Answers 4


To protect files with 3 digits already

for f in "file #"*.ext; do
  num=${f#file #}
  new=$(printf "file #%03d.ext" $num)
  echo mv "$f" "$new"

This will display in the console the commands to execute, but not actually rename the files.

Once you are happy with what it intends to do, you can make it rename the files by removing the word echo and re-running it.

  • This could've saved me a step earlier. I've been doing it all with sed, and used ls | grep '[0-9]\{3\}' | sed 's|\(.*\)#0\(.*\)|mv "&" "\1#\2"|' | sh just to make them have two digits, and then did it the way I listed above.
    – Rob
    Oct 30, 2011 at 15:20
  • I've changed this to the answer, now that I'm learning more about all of this, this is more practical and adaptable.
    – Rob
    Nov 8, 2011 at 18:44
  • One can use the -v option to printf: printf -v new "file #%03d.ext" $num Nov 1, 2012 at 22:19

You don't need sed for this. It can be done with a very simple command:

rename 's/#0/#00/' *.ext


temp$ ls
file #01.ext  file #02.ext  file #03.ext  file #04.ext  file #05.ext
temp$ rename 's/#0/#00/' *.ext
temp$ ls
file #001.ext  file #002.ext  file #003.ext  file #004.ext  file #005.ext
  • I don't have perl rename installed.
    – Rob
    Nov 2, 2012 at 22:32
  • I lied, I used to not have it installed but I do on this archlinux install.
    – Rob
    Nov 2, 2012 at 22:39

This does the trick from within the folder:

ls | sed 's/\(.*\)#\(.*\)/mv "&" "\1#0\2"/' | sh
  • ls piped to sed piped to sh? My brain is melting.
    – phogg
    Nov 4, 2011 at 13:14
  • The you probably don't want to see find piped through grep piped through sed piped to sh. :D
    – Rob
    Nov 4, 2011 at 13:48
  • Any particular reason this is bad?
    – Rob
    Nov 4, 2011 at 14:50
  • In fact, I'd be much better with find -> generate shell code. The reason for this is that find is less likely to mangle filenames than ls. In the real world I'd just use mmv for this, or a while read command substitution loop pulling nul-terminated filenames from find. Or, if the files are nicely globbable, a simple for loop as glenn used in his answer.
    – phogg
    Nov 4, 2011 at 17:42

This is a hybrid solution:

ls | sed -r "s/(.*#)([0-9]+)([^0-9]*)/printf 'mv -v \"&\" \"%s%03d%s\"' \"\1\" \"\2\" \"\3\"/e;e"

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.