Renaming hundreds of files at once for proper sorting
Ubuntu comes with a script called rename
. It's just a little Perl script that features a number of powerful bulk-renaming features but the best (in this case) is the ability for it to run Perl during the replacement. The result is a truly compact solution:
rename 's/\d+/sprintf("%05d", $&)/e' *.jpg
This is similar to the other printf
-style answers here but it's all handled for us. The code above is for a 5-digit number (including a variable number of leading zeros).
It will search and replace the first number-string it finds with a zero-padded version and leave the rest of the filename alone. This means you don't have to worry too much about carrying any extension or prefix over.
Note: this is not completely portable. Many distributions use rename.ul
from the util-linux
package as their default rename
binary. This is a significantly stunted alternative (see man rename.ul
) which won't understand the above. If you'd like this on a platform that isn't using Perl's rename, find out how to install that first.
And here's a test harness:
$ touch {1..19}.jpg
$ ls
10.jpg 12.jpg 14.jpg 16.jpg 18.jpg 1.jpg 3.jpg 5.jpg 7.jpg 9.jpg
11.jpg 13.jpg 15.jpg 17.jpg 19.jpg 2.jpg 4.jpg 6.jpg 8.jpg
$ rename 's/\d+/sprintf("%05d", $&)/e' *.jpg
$ ls
00001.jpg 00005.jpg 00009.jpg 00013.jpg 00017.jpg
00002.jpg 00006.jpg 00010.jpg 00014.jpg 00018.jpg
00003.jpg 00007.jpg 00011.jpg 00015.jpg 00019.jpg
00004.jpg 00008.jpg 00012.jpg 00016.jpg
And an example prefixes (we aren't doing anything different):
$ touch track_{9..11}.mp3 && ls
track_10.mp3 track_11.mp3 track_9.mp3
$ rename 's/\d+/sprintf("%02d", $&)/e' *.mp3 && ls
track_09.mp3 track_10.mp3 track_11.mp3
for f in *.jpg ; do if [[ $f =~ [0-9]+\. ]] ; then mv $f `printf "%.5d" "${f%.*}"`.jpg ; fi ; done
Edit
Explanation:
-
if [[ $f =~ [0-9]+\. ]]
makes sure that only files whose names are numbers (followed by a dot) are being renamed. -
printf "%.5d" NUMBER
adds the leading zeroes -
"${f%.*}"
cuts the extension (.jpg) and leaves just the number -
.jpg
after the second backtick adds the file extension again.
Note that this will work only on file names that are numbers. Left-padding leading zeroes to non-numbered files would require different format.
If you want to experiment try this command:
for f in *.jpg ; do if [[ $f =~ [0-9]+\. ]] ; then echo mv $f `printf "%.5d" "${f%.*}"`.jpg ; fi ; done
Edit 2
Made the command safer by making sure that only file names that are numbers are being renamed. Note that any pre-existing files named like 00001.jpg will be overwritten.