Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I have a ton of files, all named stuff like 1.jpg, 2.jpg, 3.jpg, and so on up to 1439.jpg, however, I have a problem with one of my projects and alphabetizing. It will usually go in the order 1.jpg, 10.jpg, 11.jpg and so on.

What I need is some way to name the files so they are in the format such as 00001.jpg all the way up to 01439.jpg.

How would I be able to do this quickly and efficiently?

share|improve this question
    
What you are looking for is "natural sorting", maybe this helps: askubuntu.com/questions/41390/… –  Fabian Blechschmidt May 28 at 12:25
    
Answer that isn't a direct answer? ls -v unix.stackexchange.com/questions/33909/… –  WernerCD May 28 at 13:28
    
+1 because I have tried unsuccessfully to do this in pyrenamer. –  Parto May 28 at 14:30
    
@FabianBlechschmidt, I need this in a program which isn't for nautilus or similar. It is for an individual project. –  Whaaaaaat May 29 at 20:29
    
I think you thought about implementing natural sorting? But I understand, renaming files is quite easy and if it does the job, great :) –  Fabian Blechschmidt May 30 at 9:39

6 Answers 6

up vote 21 down vote accepted

Ubuntu ships with a Perl script called rename. This script 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
share|improve this answer
    
If I were a Perl person this would be the perfect solution. Really neat. –  Manuel Gutierrez May 28 at 12:55
1  
It doesn't use any perl, just a tool supplied that's already written in perl. –  Rob May 28 at 16:22
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
  • .jpgafter 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.

share|improve this answer

Below a python script.

The script adds leading zeros up to the defined number of digits. If the name is larger than that, the file(name) is untouched.

Combining different extensions in one rename action might add some convenience. To add extension(s), simply add them to the tuple, for example extensions = (".jpg", ".jpeg", ".tiff").

Copy the text into an empty file, save it as rename.py, enter the correct path to the files directory (sourcedir), the number of digits you'd like the new names to have (number_ofdigits) and the file extension(s) to rename (extensions)

Run it by the command:

python3 /path/to/script/rename.py

The script:

#!/usr/bin/python3

import shutil
import os

sourcedir = "/path/to/files"; number_ofdigits = 5; extensions = (".jpg", ".jpeg")

files = os.listdir(sourcedir)
for item in files:
    if item.endswith(extensions):
        name = item.split("."); zeros = number_ofdigits-len(name[0])
        newname = str(zeros*"0")+name[0]+"."+name[1]
        shutil.move(sourcedir+"/"+item, sourcedir+"/"+newname)

edit:

Below a slightly improved version. It automatically determines the longest name in the directory, and adds leading zeros up to the length of the longest name.

example:

1.jpg
12.jpg
123.jpg

becomes:

001.jpg
012.jpg
123.jpg

No need to set the number of digits.

#!/usr/bin/python3

import shutil
import os

sourcedir = "/path/to/files"; extensions = (".jpg", ".jpeg")
files = [(f, f[f.rfind("."):], f[:f.rfind(".")]) for f in os.listdir(sourcedir)if f.endswith(extensions)]
maxlen = len(max([f[2] for f in files], key = len))

for item in files:
    zeros = maxlen-len(item[2])
    shutil.move(sourcedir+"/"+item[0], sourcedir+"/"+str(zeros*"0")+item[0])
share|improve this answer

There is a rename utility implemented in Perl that makes this very easy:

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

The first argument is a Perl expression that is evaluated for each file name.

share|improve this answer

There is a GUI that will do this called pyRenamer which can be found in the repositories. Install, start, select your directory and just set the 'Renamed file name pattern' to '{num5}'on the 'Patterns' tab and click the 'Rename' button. You can also preview what will happen prior to renaming.

share|improve this answer
    
While your answer DOES work, please note that this is a shell-scripting section, meaning I am looking for a commandline answer. Also, can you provide more detail about the program? For instance, what pattern format is {num5}? –  Whaaaaaat Jun 29 at 5:04
for file in `(find * -maxdepth 1 -type f -name "*.jpg")`     
do    
  mv $file "000"$file    
done

This is crude, since it doesn't do the renaming intelligently, will need to think of a trick for that. But it should help you sort stuff.

Update: Well you have a more complete answer.

share|improve this answer
2  
it renames 1439.jpg as 0001439.jpg. –  Avinash Raj May 28 at 5:28
    
Yes, I know, just padded extra zeroes which should still work with the sort. –  Swarnendu Biswas May 28 at 12:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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