From 7ce680b112c98c2a77d6bee58fbb20ac029876c9 Mon Sep 17 00:00:00 2001 From: Harrison Date: Thu, 6 Apr 2023 00:40:28 -0500 Subject: [PATCH] Added option to retain original file extensions --- renamebycsv.py | 133 ------------------------------------- renamebycsv/renamebycsv.py | 14 +++- 2 files changed, 13 insertions(+), 134 deletions(-) delete mode 100755 renamebycsv.py diff --git a/renamebycsv.py b/renamebycsv.py deleted file mode 100755 index 42c2cb9..0000000 --- a/renamebycsv.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import csv -import os -import re -from typing import Iterable -import logging - - -def find_all_candidates(input_dir: str, regex: str, recursive: bool): - results = [] - for subitem in os.listdir(input_dir): - subitem_path = os.path.join(input_dir, subitem) - match = re.match(regex, subitem) - if os.path.isdir(subitem_path) and recursive: - logging.debug(f'Checking directory "{subitem}"...') - results.extend(find_all_candidates(subitem_path, regex, recursive)) - else: - if not match: - logging.debug(f'Ignoring "{subitem}"...') - continue - results.append((subitem_path, subitem, match)) - logging.debug(f'Collecting "{subitem}"...') - return results - - -def rename( - csv_path: str, - candidates: Iterable[tuple[str, str, re.Match]], - current: str, - become: str, - dry: bool, -): - replacement_dict = {} - with open(csv_path, "r") as csv_fd: - reader = csv.reader(csv_fd) - current_col_ind = None - become_col_ind = None - for row in reader: - if current_col_ind is None and become_col_ind is None: - current_col_ind = row.index(current) - become_col_ind = row.index(become) - continue - if ( - row[current_col_ind] in replacement_dict - and replacement_dict[row[current_col_ind]] != row[become_col_ind] - ): - raise Exception("Duplicate current key.") - replacement_dict[row[current_col_ind]] = row[become_col_ind] - for subitem_path, subitem, match in candidates: - original = subitem_path - objective = os.path.join( - os.path.dirname(subitem_path), - re.sub(match.re, replacement_dict[match.group(1)], subitem), - ) - logging.info(f'Will rename "{original}" to "{os.path.basename(objective)}"') - if os.path.exists(objective): - logging.error( - f'Path at "{objective}" exists, not continuing. ' - "Use -f to overwrite instead of stopping." - ) - exit(1) - if not dry: - os.rename(original, objective) - if dry: - logging.info("No file names were modified.") - - -def main(): - program_name = "renamebycsv" - argparser = argparse.ArgumentParser( - program_name, "Rename all files by using a CSV as a dictionary." - ) - argparser.add_argument( - "input_dir", - help="The directory containing the items that is to be renamed.", - metavar="I", - ) - argparser.add_argument( - "regex", - help="The regex to apply to each file name. The first capture group is used to " - "perform the replacement.", - metavar="R", - ) - argparser.add_argument( - "csv", - help="The CSV to use as the dictionary for the substitutions in file name.", - metavar="C", - ) - argparser.add_argument( - "current", - help="The column header to look for the text matched by the regex.", - metavar="F", - ) - argparser.add_argument( - "become", help="The column header to replace the regex match.", metavar="T" - ) - argparser.add_argument( - "-r", - "--recursive", - help="Perform renaming action recursively", - action="store_true", - ) - argparser.add_argument( - "-f", - "--force", - help="Overwrite files if file already exists", - action="store_true", - ) - argparser.add_argument( - "-d", "--dry", help="Do not perform any renames", action="store_true" - ) - argparser.add_argument( - "-V", - "--verbosity", - help="Set the logging verbosity", - required=False, - type=str, - default="INFO", - ) - - args = argparser.parse_args() - logging.basicConfig( - format="[%(filename)s %(asctime)s - %(levelname)s] %(message)s", - level=args.verbosity.upper(), - ) - candidates = find_all_candidates(args.input_dir, args.regex, args.recursive) - rename(args.csv, candidates, args.current, args.become, args.dry) - - -if __name__ == "__main__": - main() diff --git a/renamebycsv/renamebycsv.py b/renamebycsv/renamebycsv.py index 42c2cb9..26cbd20 100755 --- a/renamebycsv/renamebycsv.py +++ b/renamebycsv/renamebycsv.py @@ -31,6 +31,7 @@ def rename( current: str, become: str, dry: bool, + keep_extension: bool, ): replacement_dict = {} with open(csv_path, "r") as csv_fd: @@ -54,6 +55,8 @@ def rename( os.path.dirname(subitem_path), re.sub(match.re, replacement_dict[match.group(1)], subitem), ) + if keep_extension: + objective += os.path.splitext(subitem_path)[1] logging.info(f'Will rename "{original}" to "{os.path.basename(objective)}"') if os.path.exists(objective): logging.error( @@ -119,6 +122,13 @@ def main(): type=str, default="INFO", ) + argparser.add_argument( + "-k", + "--keep-extension", + help="Keeps the original file's extension by appending it to the end of the " + "name defined by the CSV.", + action="store_true", + ) args = argparser.parse_args() logging.basicConfig( @@ -126,7 +136,9 @@ def main(): level=args.verbosity.upper(), ) candidates = find_all_candidates(args.input_dir, args.regex, args.recursive) - rename(args.csv, candidates, args.current, args.become, args.dry) + rename( + args.csv, candidates, args.current, args.become, args.dry, args.keep_extension + ) if __name__ == "__main__":