[tab] scripts/rename_mp4_files.py (python)
#!/usr/bin/env python3
"""
Script to rename all MP4 files in a directory with a custom prefix.
"""

import os
import argparse
import re
from pathlib import Path


def rename_mp4_files(directory, prefix, dry_run=False, pattern=None, start_number=1):
    """
    Rename all MP4 files in the specified directory with a custom prefix.
    
    Args:
        directory (str): Path to the directory containing MP4 files
        prefix (str): Custom prefix to add to filenames
        dry_run (bool): If True, only show what would be renamed without actually renaming
        pattern (str): Optional regex pattern to filter files
        start_number (int): Starting number for sequential naming
    """
    directory_path = Path(directory)
    
    if not directory_path.exists():
        print(f"Error: Directory '{directory}' does not exist.")
        return
    
    if not directory_path.is_dir():
        print(f"Error: '{directory}' is not a directory.")
        return
    
    # Find all MP4 files
    mp4_files = list(directory_path.glob("*.mp4"))
    
    if not mp4_files:
        print(f"No MP4 files found in '{directory}'")
        return
    
    # Filter by pattern if provided
    if pattern:
        regex = re.compile(pattern)
        mp4_files = [f for f in mp4_files if regex.search(f.name)]
    
    if not mp4_files:
        print(f"No MP4 files match the pattern '{pattern}' in '{directory}'")
        return
    
    print(f"Found {len(mp4_files)} MP4 files to rename:")
    
    # Sort files for consistent ordering
    mp4_files.sort()
    
    for i, file_path in enumerate(mp4_files, start=start_number):
        # Get the original filename without extension
        original_name = file_path.stem
        extension = file_path.suffix
        
        # Create new filename with prefix
        new_name = f"{prefix}_{i:03d}_{original_name}{extension}"
        new_path = file_path.parent / new_name
        
        # Check if new filename already exists
        if new_path.exists() and not dry_run:
            print(f"Warning: '{new_name}' already exists, skipping '{file_path.name}'")
            continue
        
        if dry_run:
            print(f"Would rename: '{file_path.name}' -> '{new_name}'")
        else:
            try:
                file_path.rename(new_path)
                print(f"Renamed: '{file_path.name}' -> '{new_name}'")
            except OSError as e:
                print(f"Error renaming '{file_path.name}': {e}")
    
    if dry_run:
        print(f"
Dry run completed. {len(mp4_files)} files would be renamed.")
    else:
        print(f"
Renaming completed. {len(mp4_files)} files renamed.")


def main():
    parser = argparse.ArgumentParser(
        description="Rename all MP4 files in a directory with a custom prefix",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s /path/to/videos minecraft
  %(prog)s /path/to/videos player --dry-run
  %(prog)s /path/to/videos episode --pattern "joost" --start-number 10
        """
    )
    
    parser.add_argument(
        "directory",
        help="Directory containing MP4 files to rename"
    )
    
    parser.add_argument(
        "prefix",
        help="Custom prefix to add to filenames"
    )
    
    parser.add_argument(
        "--dry-run",
        action="store_true",
        help="Show what would be renamed without actually renaming files"
    )
    
    parser.add_argument(
        "--pattern",
        help="Regex pattern to filter files (only rename files matching this pattern)"
    )
    
    parser.add_argument(
        "--start-number",
        type=int,
        default=1,
        help="Starting number for sequential naming (default: 1)"
    )
    
    args = parser.parse_args()
    
    # Validate start number
    if args.start_number < 1:
        print("Error: start-number must be at least 1")
        return
    
    rename_mp4_files(
        directory=args.directory,
        prefix=args.prefix,
        dry_run=args.dry_run,
        pattern=args.pattern,
        start_number=args.start_number
    )


if __name__ == "__main__":
    main()