Take the 2-minute tour ×

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?

share|improve this question
add comment

4 Answers

up vote 2 down vote accepted

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.

share|improve this answer
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 '11 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 '11 at 18:44
One can use the -v option to printf: printf -v new "file #%03d.ext" $num –  glenn jackman Nov 1 '12 at 22:19
add comment

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
share|improve this answer
I don't have perl rename installed. –  Rob Nov 2 '12 at 22:32
I lied, I used to not have it installed but I do on this archlinux install. –  Rob Nov 2 '12 at 22:39
add comment

This is a hybrid solution:

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

This does the trick from within the folder:

ls | sed 's/\(.*\)#\(.*\)/mv "&" "\1#0\2"/' | sh
share|improve this answer
ls piped to sed piped to sh? My brain is melting. –  phogg Nov 4 '11 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 '11 at 13:48
Any particular reason this is bad? –  Rob Nov 4 '11 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 '11 at 17:42
add comment

Your Answer


