5

I would like to rename all files in a folder so to have consecutive numbers. For instance:

1.png
2.png
3.png
etc

I know there is the rename command and I know there are DOZENS of similar questions in here but I can't find the way.

NOTE: Suggested duplicate doesn't contain a solution specific for my case. Please stop flagging this as duplicate, because suggested duplicate does not answer my question

  • 1
    Which file will be 1.png? Shell globbing order? – heemayl Aug 6 '16 at 20:06
  • @heemayl I don't really understand what you mean but the 1.png I want to be the first file in the folder. – Adam Aug 6 '16 at 20:07
  • 1
    @Adam He's asking how you have the files sorted. The shell sorts them one way according to name, but you might want them sorted by last modified date, a different way by name, etc. – wjandrea Aug 6 '16 at 21:45
  • 2
    @Serg The files are named with the default name of the Screenshot software of Ubuntu. – Adam Aug 6 '16 at 22:05
  • 2
    CLOSE-VOTERS: as shown in the comments, OP specifically stated that he tried the suggested duplicate and it did not work. Please retract your votes. See meta.stackexchange.com/a/194479/295160 – Sergiy Kolodyazhnyy Aug 7 '16 at 20:05
9

Assuming you want to follow the shell globbing order while sorting files, you can do:

#!/bin/bash
counter=0
for file in *; do 
    [[ -f $file ]] && echo mv -i "$file" $((counter+1)).png && ((counter++))
done

Here looping over all the files in the current directory and renaming sequentially based on order, if you want to deal with only the .png files, use for file in *.png instead. counter variable will keep track of the increments.

This is a dry-run, remove echo to let the actual renaming action take place.

Example:

$ counter=0; for file in *; do [[ -f $file ]] && echo mv -i "$file" $((counter+1)).png && ((counter++)); done
mv -i file.txt 1.png
mv -i foo.sh 2.png
mv -i bar.txt 3.png
  • You should put quotes around $file to avoid breaking on spaces, and put ((counter++)) inside an if statement to avoid incrementing on directories. – wjandrea Aug 6 '16 at 21:40
  • @wjandrea You don't need to quote when using bash keyword [[ (unlike [), [[ is a keyword, bash handles it internally as well as the word splitting and filename expansion too, hence no quoting needed. You're right about the second one, forgot that. Edited..thanks.. – heemayl Aug 6 '16 at 21:46
  • Don't forget to check whether any of your destination filenames already exists in the directory. Suppose you run the script once, add a few files, and then try to run it again. What happens? – Dave Tweed Aug 7 '16 at 0:04
  • @DaveTweed that's what the -i option of mv will do.. – heemayl Aug 7 '16 at 0:12
  • What is what the -i option does? Even if you skip overwriting a file, you still won't end up with the correct result. – Dave Tweed Aug 7 '16 at 0:15
2

Here's a small python script that can do what you ask

Basic usage:

python rename_files.py Pictures/

It will print output to stdout before renaming each file

This version pushes index until it is found that filename with such index is not taken. Although filenames may start at different index upon successive iterations of the script, the files themselves remain unchanged.

import os
import sys

top_dir = os.path.abspath(sys.argv[1])
files = os.listdir( top_dir )

for index,item in enumerate(files):
    if os.path.isdir( os.path.join(top_dir,item) ):
       files.pop(index)

files.sort()

duplicates = []
last_index = None
for index,item in enumerate(files):

    last_index = index
    extension = ""
    if '.' in item:
        extension = '.' + item.split('.')[-1]
    old_file = os.path.join(top_dir,item)
    new_file = os.path.join(top_dir,str(index) + extension  )
    while os.path.isfile(new_file):
          last_index += 1
          new_file = os.path.join(top_dir,str(last_index) + extension  )
    print( old_file + ' renamed to ' + new_file ) 
    os.rename(old_file,new_file)

Alternative version, solves issue with duplicate filenames by appending timestamp to each filename, and then enumerating them. This solution may take longer time, as number of files increases, but for directories that range in hundreds , this won't take long time

import os
import sys
import time

top_dir = os.path.abspath(sys.argv[1])
files = os.listdir( top_dir )

for index,item in enumerate(files):
    if os.path.isdir( os.path.join(top_dir,item) ):
       files.pop(index)

files.sort()
timestamp = str(int(time.time()))
for item in files:
    os.rename( os.path.join(top_dir,item) ,
               os.path.join(top_dir, timestamp + item) )

files2 = os.listdir( top_dir )

for index,item in enumerate(files2):
    if os.path.isdir( os.path.join(top_dir,item) ):
       files2.pop(index)

for index,item in enumerate( files2  ):

    last_index = index
    extension = ""
    if '.' in item:
        extension = '.' + item.split('.')[-1]
    old_file = os.path.join(top_dir,item)
    new_file = os.path.join(top_dir,str(index) + extension  )

    while os.path.isfile(new_file):
          last_index += 1
          new_file = os.path.join(top_dir,str(last_index) + extension  )
    print( old_file + ' renamed to ' + new_file ) 
    os.rename(old_file,new_file)
  • Don't forget to check whether any of your destination filenames already exists in the directory. Suppose you run the script once, add a few files, and then try to run it again. What happens? – Dave Tweed Aug 7 '16 at 0:05
  • @DaveTweed can you provide an example ? running script twice wouldn't have issue with duplicates, because entries are sorted and enumerated each time. So if 1.png already exists, it would get sorted and renamed to 1.png again – Sergiy Kolodyazhnyy Aug 7 '16 at 0:14
  • Suppose I run the script to produce 1.png through 10.png. Then I add the file 3a.png, which should be renamed to 4.png, which already exists -- not to mention the renaming all of the files after that. – Dave Tweed Aug 7 '16 at 0:17
  • Note that just having 1.png through 10.png by itself is a problem -- on the second run, you'll want to rename 10.png to 2.png, creating the same problem. – Dave Tweed Aug 7 '16 at 0:20
  • @DaveTweed is this the case you mean ? paste.ubuntu.com/22518702 – Sergiy Kolodyazhnyy Aug 7 '16 at 0:48

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.