2 min read

Regex File Renamer

This utility automates batch file renaming using Regular Expressions (Regex). It allows you to search for complex patterns in filenames and replace them with a new format using capture groups.

Modules Used:

  • re: To handle regular expression matching and substitution.
  • os: To perform the actual file renaming.
  • argparse: To handle command-line arguments.

The Code

Save this as regex_rename.py.

import re
import os
import argparse
import sys

def batch_rename(directory, pattern, replacement, dry_run=False):
    if not os.path.exists(directory):
        print(f"Error: Directory '{directory}' not found.")
        return

    print(f"Scanning '{directory}'...")
    print(f"Pattern: r'{pattern}' -> '{replacement}'")

    count = 0

    try:
        # Compile regex for performance
        regex = re.compile(pattern)
    except re.error as e:
        print(f"Error: Invalid regex pattern. {e}")
        return

    for filename in os.listdir(directory):
        # Skip directories
        if os.path.isdir(os.path.join(directory, filename)):
            continue

        # Check for match
        if regex.search(filename):
            # Generate new name
            # re.sub uses \1, \2 etc. for backreferences to capture groups
            new_name = regex.sub(replacement, filename)

            if new_name == filename:
                continue

            old_path = os.path.join(directory, filename)
            new_path = os.path.join(directory, new_name)

            if os.path.exists(new_path):
                print(f"Skipping: '{new_name}' already exists.")
                continue

            if dry_run:
                print(f"[DRY RUN] Rename: '{filename}' -> '{new_name}'")
            else:
                try:
                    os.rename(old_path, new_path)
                    print(f"Renamed: '{filename}' -> '{new_name}'")
                except OSError as e:
                    print(f"Error renaming '{filename}': {e}")

            count += 1

    if count == 0:
        print("No files matched the pattern.")
    else:
        print(f"\nProcessed {count} files.")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Batch File Renamer using Regex")
    parser.add_argument("directory", help="Target directory")
    parser.add_argument("pattern", help="Regex pattern to match (e.g., 'img_(\d+)')")
    parser.add_argument("replacement", help="Replacement pattern (e.g., 'photo_\\1')")
    parser.add_argument("--dry-run", action="store_true", help="Show what would happen without renaming")

    args = parser.parse_args()

    batch_rename(args.directory, args.pattern, args.replacement, args.dry_run)

Usage

# Preview changes (Dry Run)
# Rename 'img_001.jpg' to 'photo_001.jpg'
# Note: Use \\1 for backreferences in the command line to ensure python receives \1
python regex_rename.py ./photos "img_(\d+)" "photo_\\1" --dry-run

# Execute renaming
# Change date format from '2023-01-01_report.txt' to 'report_2023-01-01.txt'
python regex_rename.py ./docs "(\d{4}-\d{2}-\d{2})_(.*)\.txt" "\\2_\\1.txt"

programming/python/python