Friday, January 19, 2018

How to Rename Multiple Files Efficiently

Sometimes we want to rename a bulk of files at once. Windows Explorer provides this bulk renaming feature. We can select the files we want to rename (Ctrl + Left click) then press F2 to enter the new name for them. Windows Explorer renames the each of the files with new name plus a numbering.

Rename files with Windows Explorer

What if we want to rename files with a specific pattern? Command Prompt comes to rescue. We use REN command to achieve this. With REN command we can rename files with wildcards? and/or *. Let's say we have video files, we want to rename the files that start with "2" and end with ".mkv" into first 2 characters and ends with its extension. The command is:

REN 2*.mkv ??.???

'*' matches any number of characters. So the first parameter means: all files with name starts with '2' and ends with 'mkv'. '?' match a single character. So the second parameters mean first two characters of a filename, followed by '.' (dot), followed by three characters after the dot of the filename.

Rename files with REN command (1)
Here is the result:

Rename files with REN command (2)
So far so good, but what if we want the new name consists of matched patterns of the old name? What if we want the new name to be the characters between first character and extension? We might not achieve this with REN command. We need regular expressions to do this. Since REN does not support regular expression and most of Windows installation disable PowerShell script by default, we use Python to implement this.

Rename files with Python (1)
Suppose we want the number part of those files to be the first part switch place with the alphabet part. Below is the Python code:

import os, re

path = 'C:/Users/Test/test'
pattern = '^([A-Z]+)\-([0-9]+).*$'
replace = r"\2-\1.mkv"

comp = re.compile(pattern)
for f in os.listdir(path):
    full_path = os.path.join(path, f)
    if os.path.isfile(full_path):
     
        match = comp.search(f)
        if not match :
           continue

        try:
            new_name = match.expand(replace)
            new_name = os.path.join(path, new_name)
        except re.error:
            continue
     
        if os.path.isfile(new_name):
            print('%s -> %s skipped' % (f, new_name))
        else:
            os.rename(full_path, new_name)


The path variable is, obviously, the absolute path where the files in. The pattern variable is the regular expression of a filename you want to match. The replace variable is the new file name pattern you wish to. You notice that there are \1 and \2 in the replacement pattern. They represent the subgroup match. \1 is the first parenthesized subgroup, the characters that match [A-Z]+ pattern. \2 is the second parenthesized subgroup, the characters that match [0-9]+ pattern.

Here is the result of that Python code:

Rename files with Python (2)
I have wrapped this code into a batch script file, check out my gist. You need to place these files in a path of your PATH environment variable. To run this program, cd to target directory then enter this command:

regex_rename "<pattern>" "<replacement_pattern>"

Example:

regex_rename "^([A-Z]+)\-([0-9]+).*$" "\2-\1.mkv"

Please leave a comment for suggestion or improvement.

No comments:

Post a Comment