7

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

10
  • 1
    Which file will be 1.png? Shell globbing order?
    – heemayl
    Commented Aug 6, 2016 at 20:06
  • 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
    Commented Aug 6, 2016 at 21:45
  • 2
    @Serg The files are named with the default name of the Screenshot software of Ubuntu.
    – Adam
    Commented Aug 6, 2016 at 22:05
  • 1
    By the way , what if the folder contains subfolders ? Leave those alone or give it a number as well ? Commented Aug 6, 2016 at 22:21
  • 3
    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 Commented Aug 7, 2016 at 20:05

2 Answers 2

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
7
  • You should put quotes around $file to avoid breaking on spaces, and put ((counter++)) inside an if statement to avoid incrementing on directories.
    – wjandrea
    Commented Aug 6, 2016 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
    Commented Aug 6, 2016 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
    Commented Aug 7, 2016 at 0:04
  • @DaveTweed that's what the -i option of mv will do..
    – heemayl
    Commented Aug 7, 2016 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
    Commented Aug 7, 2016 at 0:15
3

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)
12
  • 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
    Commented Aug 7, 2016 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 Commented Aug 7, 2016 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
    Commented Aug 7, 2016 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
    Commented Aug 7, 2016 at 0:20
  • @DaveTweed is this the case you mean ? paste.ubuntu.com/22518702 Commented Aug 7, 2016 at 0:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .