Skip to content
Advertisement

How to rename files chronologically without changing their order?

I made an application in Python (link for source code at the bottom) which renames files (in a directory) by sorting them (based on their extension) into one of these: Image, Video, Text, GIF, Audio and Unknown Extension.

Basically, it loops through a directory, gets all the files in it, sorts them, for each file in the sorted list it assigns a value of its index in list and then renames the file. But, for some reason, it gives the same number twice or misses some in between.

So, I would like to rename them in chronological order, without changing the order in which they appear. For example, the third file before the process should be the same as the third file after the process and so on. like this:

Goal

I don’t know how to put my thoughts into Python’s code. But I think you can do it like this:

  1. Get all the files in a folder (Chronologically).
  2. If they contain a specific word (like Image or video), add them to the list named after the word it contains.
  3. Get the length(or count) of the list.
  4. In a for loop, split the file name by ' ' (Space). Check if the RHS of the name corresponds to the current value of loop, if it doesn’t rename it with the same name but this new value.

Minimal code to copy this error:

import os
choice = "Subdirectories included"
values = dict ({
    "unknownCount" : 0,
    "textCount" : 0,
    "imageCount" : 0,
    "gifCount" : 0,
    "audioCount" : 0,
    "videoCount" : 0,
})
    os.chdir(location)
    if choice == "Subdirectories included":
        for root, dirs, files in os.walk(location):
            for i in sorted(files):
                fileName = os.path.join(root,i)
                if fileName.__contains__('.'):
                    ext = fileName.split('.')[1]
                    toR = Give(ext) + "." + ext
                    toRename = root + toR
                try:
                    os.rename(fileName, toRename)
                except: 
                    error = OSError
                    print(error)    
def Give(ext):
    addUnknown = True
    
    if ext == "txt":
        toname = "Text " + str(values["textCount"])
        values["textCount"] += 1
        addUnknown = False
    elif ext == "jpg":
        toname = "Image " + str(values["imageCount"])
        values["imageCount"] += 1
        addUnknown = False
    elif ext == "jpeg":
        toname = "Image " + str(values["imageCount"])
        values["imageCount"] += 1
        addUnknown = False
    elif ext == "png":
        toname = "Image " + str(values["imageCount"])
        values["imageCount"] += 1
        addUnknown = False
    elif ext == "gif":
        toname = "GIF " + str( values["gifCount"])
        values["gifCount"] += 1
        addUnknown = False
    elif ext == "mp3":
        toname = "Audio " + str(values["audioCount"])
        values["audioCount"] += 1
        addUnknown = False
    elif ext == "ogg":
        toname = "Audio " + str(values["audioCount"])
        values["audioCount"] += 1
        addUnknown = False
    elif ext == "wav":
        toname = "Audio " + str(values["audioCount"])
        values["audioCount"] += 1
        addUnknown = False
    elif ext == "mkv":
        toname = "Video " + str(values["videoCount"])
        values["videoCount"] += 1
        addUnknown = False
    elif ext == "avi":
        toname = "Video " + str(values["videoCount"])
        values["videoCount"] += 1
        addUnknown = False
    elif ext == "mp4":
        toname = "Video " + str(values["videoCount"])
        values["videoCount"] += 1
        addUnknown = False

    if addUnknown == True:
        toname = r"Unknown Extension " + str(values["unknownCount"])
        values["unknownCount"] += 1

    return toname

Advertisement

Answer

Assumed (from the image in the question) that there is a unique format of basename per file extension: format .jpg -> name format Image D where D is a digit(s). Those which do not satisfy the format are treated (and recorded) as exceptions and no actions is performed on them. For more complex situations a regex approach is suggested.

Idea: group by file extensions, sort each group, set new name, rename

Note

  • as first run maybe comment the line with os.rename
  • it has been tested only in current directory

Here a possible approach:

import os

# path of the dir
path_dir = '.'

# get all file extensions in the directory
exts = [f.split('.')[-1] for f in os.listdir(path_dir)]

# get all file names in the directory
files = os.listdir(path_dir)

# group by file extension & format
groupby_ext = {}
for f in files:
    for ext in exts:
        if f.endswith(ext):
            # check file format condition
            if ' ' in f:
                groupby_ext.setdefault(ext, set()).add(f[:-len(ext)-1])
            else:
                # those who do NOT satisfy the name format conditions
                groupby_ext.setdefault('exceptions', []).append(f)


for ext, files in groupby_ext.items():
    if ext == 'exceptions':
        continue
    # sort by name and rename
    for i, bname in enumerate(sorted(files, key=lambda s: int(s.split()[-1]))):
        # new name
        new_bname = f'{bname.split()[0]} {i}.{ext}'

        # change name
        print(bname, '-->', new_bname)
        os.rename(f'{bname}.{ext}', new_bname) # maybe comment this line before running the program

# no actions on them
print(groupby_ext['exceptions'])
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement