Rename all files in a folder to consecutive numbers
Solution 1
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
Solution 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)
Related videos on Youtube
Adam
Updated on September 18, 2022Comments
-
Adam over 1 year
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
-
heemayl almost 8 yearsWhich file will be
1.png
? Shell globbing order? -
Adam almost 8 years@heemayl I don't really understand what you mean but the 1.png I want to be the first file in the folder.
-
wjandrea almost 8 years@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.
-
Sergiy Kolodyazhnyy almost 8 yearsYou might want to provide example of how files are named in the folder. This can be easily done, but we need to know what the original filenams will be.
-
Adam almost 8 years@wjandrea Oh I want them sorted based on their name i.e. 1 first 2 second etc...
-
Adam almost 8 years@Serg The files are named with the default name of the Screenshot software of Ubuntu.
-
Sergiy Kolodyazhnyy almost 8 yearsOk , let me sketch up a small script, i'll post it in about 20 mins or so
-
Sergiy Kolodyazhnyy almost 8 yearsBy the way , what if the folder contains subfolders ? Leave those alone or give it a number as well ?
-
Sergiy Kolodyazhnyy almost 8 yearsPosted answer, please review
-
Sergiy Kolodyazhnyy almost 8 yearsCLOSE-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
-
-
wjandrea almost 8 yearsYou should put quotes around
$file
to avoid breaking on spaces, and put((counter++))
inside anif
statement to avoid incrementing on directories. -
heemayl almost 8 years@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.. -
Dave Tweed almost 8 yearsDon'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 almost 8 yearsDon'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?
-
heemayl almost 8 years@DaveTweed that's what the
-i
option ofmv
will do.. -
Sergiy Kolodyazhnyy almost 8 years@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
-
Dave Tweed almost 8 yearsWhat 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 almost 8 yearsSuppose I run the script to produce
1.png
through10.png
. Then I add the file3a.png
, which should be renamed to4.png
, which already exists -- not to mention the renaming all of the files after that. -
Dave Tweed almost 8 yearsNote that just having
1.png
through10.png
by itself is a problem -- on the second run, you'll want to rename10.png
to2.png
, creating the same problem. -
Sergiy Kolodyazhnyy almost 8 years@DaveTweed is this the case you mean ? paste.ubuntu.com/22518702
-
Sergiy Kolodyazhnyy almost 8 yearsAlso, how's this ? paste.ubuntu.com/22518907
-
Sergiy Kolodyazhnyy almost 8 yearsI get what you're saying, but do you have any suggestion on how to avoid overwriting duplicates ?
-
Dave Tweed almost 8 yearsThere are two issues here. The first is producing a sequence of output filenames that sorts to the same sequence when read as input. The second issue is the problem of overwriting an existing file.The latter must be addressed by forming a complete mapping from input names to output names, and then before you rename any files, you check for any collisions between the two lists. If any are found, they form "chains" of two or more names that must be handled last-first. I.e., you must rename
4.png
to5.png
before you try to rename3a.png
to4.png
, and so forth. -
Dave Tweed almost 8 years... This is the difference between "software engineering" and simple hacking.
-
Sergiy Kolodyazhnyy almost 8 years@DaveTweed OK , I've edited my script somewhat to push index until there's no index that exists. Please check this: paste.ubuntu.com/22526386 Updated script is here: paste.ubuntu.com/22526509
-
Sergiy Kolodyazhnyy almost 8 yearsHere's one more with extensions paste.ubuntu.com/22526962
-
Sergiy Kolodyazhnyy almost 8 yearsLet us continue this discussion in chat.
-
heemayl almost 8 years@DaveTweed Ahhh..i see what you meant. That would need a hash and some preprocessing..this answer is necessarily an one go..
-
Jsevillamol about 5 yearsIn case somebody wants the result to be zero-padded, you can use
counter=0; for file in *; do [[ -f $file ]] && echo mv -i "$file" $(printf %03d $((counter+1))).png && ((counter++)); done