diff --git a/batch_file_rename.py b/batch_file_rename.py index b3a4d75e6d5..05fa7391916 100644 --- a/batch_file_rename.py +++ b/batch_file_rename.py @@ -1,57 +1,83 @@ -# batch_file_rename.py -# Created: 6th August 2012 - -""" -This will batch rename a group of files in a given directory, -once you pass the current and new extensions -""" - -# just checking -__author__ = "Craig Richards" -__version__ = "1.0" - import argparse -import os +import sys +from pathlib import Path -def batch_rename(work_dir, old_ext, new_ext): +def batch_rename(work_dir, old_ext, new_ext, dry_run=False): """ - This will batch rename a group of files in a given directory, - once you pass the current and new extensions + Batch rename files in a directory from one extension to another. + + Args: + work_dir (str): Path to the target directory. + old_ext (str): Extension to find (e.g., '.txt' or '.tar.gz'). + new_ext (str): New extension to apply (e.g., '.md'). + dry_run (bool): If True, preview changes without applying. """ - # files = os.listdir(work_dir) - for filename in os.listdir(work_dir): - # Get the file extension - split_file = os.path.splitext(filename) - # Unpack tuple element - root_name, file_ext = split_file - # Start of the logic to check the file extensions, if old_ext = file_ext - if old_ext == file_ext: - # Returns changed name of the file with new extention - newfile = root_name + new_ext + work_path = Path(work_dir) + if not work_path.is_dir(): + print(f"Error: {work_dir} is not a valid directory.", file=sys.stderr) + return + + # Normalize extensions for library safety + if not old_ext.startswith("."): + old_ext = "." + old_ext + if not new_ext.startswith("."): + new_ext = "." + new_ext + + print(f"[*] Scanning {work_dir} for files with extension '{old_ext}'...") + + found_files = list(work_path.glob(f"*{old_ext}")) + if not found_files: + print(f"[!] No files found with extension '{old_ext}'.") + return + + for file_path in found_files: + # Handle compound extensions by checking ends-with + if file_path.name.endswith(old_ext): + new_name = file_path.name[:-len(old_ext)] + new_ext + new_file_path = file_path.with_name(new_name) + else: + new_file_path = file_path.with_suffix(new_ext) + + if new_file_path.exists(): + print(f"[!] Skip: {new_file_path.name} already exists. Cannot rename {file_path.name}.", file=sys.stderr) + continue - # Write the files - os.rename(os.path.join(work_dir, filename), os.path.join(work_dir, newfile)) - print("rename is done!") - print(os.listdir(work_dir)) + if dry_run: + print(f"[DRY-RUN] Would rename: {file_path.name} -> {new_file_path.name}") + else: + try: + file_path.rename(new_file_path) + print(f"[+] Renamed: {file_path.name} -> {new_file_path.name}") + except OSError as e: + print(f"[!] Error renaming {file_path.name}: {e}", file=sys.stderr) + continue + + if not dry_run: + print("[*] Batch rename completed.") def get_parser(): + """ + Create and return the argument parser for the CLI. + """ parser = argparse.ArgumentParser( - description="change extension of files in a working directory" + description="Change extension of files in a working directory" ) parser.add_argument( "work_dir", - metavar="WORK_DIR", - type=str, - nargs=1, - help="the directory where to change extension", + help="The directory where to change extension", ) parser.add_argument( - "old_ext", metavar="OLD_EXT", type=str, nargs=1, help="old extension" + "old_ext", help="Old extension (e.g., .txt or txt)" ) parser.add_argument( - "new_ext", metavar="NEW_EXT", type=str, nargs=1, help="new extension" + "new_ext", help="New extension (e.g., .md or md)" + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Preview changes without applying them", ) return parser @@ -60,22 +86,14 @@ def main(): """ This will be called if the script is directly invoked. """ - # adding command line argument parser = get_parser() - args = vars(parser.parse_args()) + args = parser.parse_args() - # Set the variable work_dir with the first argument passed - work_dir = args["work_dir"][0] - # Set the variable old_ext with the second argument passed - old_ext = args["old_ext"][0] - if old_ext and old_ext[0] != ".": - old_ext = "." + old_ext - # Set the variable new_ext with the third argument passed - new_ext = args["new_ext"][0] - if new_ext and new_ext[0] != ".": - new_ext = "." + new_ext + work_dir = args.work_dir + old_ext = args.old_ext if args.old_ext.startswith(".") else "." + args.old_ext + new_ext = args.new_ext if args.new_ext.startswith(".") else "." + args.new_ext - batch_rename(work_dir, old_ext, new_ext) + batch_rename(work_dir, old_ext, new_ext, dry_run=args.dry_run) if __name__ == "__main__":