Created
August 15, 2025 12:16
-
-
Save yanli0303/95f3d81ed0da0d1255e18ca5348ddfb5 to your computer and use it in GitHub Desktop.
Rename subdirectories by regular expression
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Script to rename directories by removing trailing " (\\d\\dP)" pattern. | |
| Usage: | |
| python rename_directories.py /path/to/directory | |
| Example: | |
| python rename_directories.py ~/Desktop/videos | |
| """ | |
| import argparse | |
| import re | |
| import sys | |
| from pathlib import Path | |
| def rename_directories(base_path): | |
| """ | |
| Rename all subdirectories in the given path by removing trailing " \\(\\+P(.*)\\)" pattern. | |
| Args: | |
| base_path (str): Path to the directory containing subdirectories to rename | |
| """ | |
| base_path = Path(base_path) | |
| if not base_path.exists(): | |
| print(f"Error: Directory '{base_path}' does not exist.") | |
| return False | |
| if not base_path.is_dir(): | |
| print(f"Error: '{base_path}' is not a directory.") | |
| return False | |
| # Pattern to match "\s\(\d+P.*\)$" at the end of directory names | |
| pattern = re.compile(r"\s\(\d+P.*\)$") | |
| renamed_count = 0 | |
| error_count = 0 | |
| # Get all subdirectories | |
| subdirs = [d for d in base_path.iterdir() if d.is_dir()] | |
| if not subdirs: | |
| print(f"No subdirectories found in '{base_path}'.") | |
| return True | |
| print(f"Found {len(subdirs)} subdirectories to process...") | |
| for subdir in subdirs: | |
| dir_name = subdir.name | |
| # Check if the directory name matches the pattern | |
| if pattern.search(dir_name): | |
| new_name = pattern.sub("", dir_name) | |
| new_path = subdir.parent / new_name | |
| # Check if a directory with the new name already exists | |
| if new_path.exists(): | |
| print(f"Warning: '{new_name}' already exists. Skipping '{dir_name}'.") | |
| error_count += 1 | |
| continue | |
| try: | |
| print(f"Renaming: '{dir_name}' -> '{new_name}'") | |
| subdir.rename(new_path) | |
| renamed_count += 1 | |
| except OSError as e: | |
| print(f"Error renaming '{dir_name}': {e}") | |
| error_count += 1 | |
| else: | |
| print(f"No pattern match: '{dir_name}' (skipped)") | |
| print("\nSummary:") | |
| print(f" Directories renamed: {renamed_count}") | |
| print(f" Errors encountered: {error_count}") | |
| print(f" Total processed: {len(subdirs)}") | |
| return error_count == 0 | |
| def main(): | |
| parser = argparse.ArgumentParser( | |
| description="Remove trailing ' (\\d\\dP)' pattern from directory names", | |
| formatter_class=argparse.RawDescriptionHelpFormatter, | |
| epilog=""" | |
| Examples: | |
| python rename_directories.py ~/Downloads/movies | |
| This script will rename directories like: | |
| "Movie Name (1080P)" -> "Movie Name" | |
| "Video Title (720P)" -> "Video Title" | |
| """, | |
| ) | |
| parser.add_argument("directory", help="Path to the directory containing subdirectories to rename") | |
| parser.add_argument("--dry-run", action="store_true", help="Show what would be renamed without actually renaming") | |
| args = parser.parse_args() | |
| if args.dry_run: | |
| print("DRY RUN MODE - No actual renaming will be performed\n") | |
| dry_run_preview(args.directory) | |
| else: | |
| success = rename_directories(args.directory) | |
| sys.exit(0 if success else 1) | |
| def dry_run_preview(base_path): | |
| """Show what would be renamed in dry-run mode.""" | |
| base_path = Path(base_path) | |
| if not base_path.exists(): | |
| print(f"Error: Directory '{base_path}' does not exist.") | |
| return | |
| if not base_path.is_dir(): | |
| print(f"Error: '{base_path}' is not a directory.") | |
| return | |
| pattern = re.compile(r" \(\d{2}P\)$") | |
| subdirs = [d for d in base_path.iterdir() if d.is_dir()] | |
| if not subdirs: | |
| print(f"No subdirectories found in '{base_path}'.") | |
| return | |
| rename_candidates = [] | |
| for subdir in subdirs: | |
| dir_name = subdir.name | |
| if pattern.search(dir_name): | |
| new_name = pattern.sub("", dir_name) | |
| rename_candidates.append((dir_name, new_name)) | |
| else: | |
| print(f"No change needed: '{dir_name}'") | |
| if rename_candidates: | |
| print(f"\nThe following {len(rename_candidates)} directories would be renamed:") | |
| for old_name, new_name in rename_candidates: | |
| print(f" '{old_name}' -> '{new_name}'") | |
| else: | |
| print("No directories match the pattern for renaming.") | |
| if __name__ == "__main__": | |
| main() |
Author
TODO:
- Accept Regular Expression as input.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.