Python script to remove strings from filenames and directory names recursively
This Python script renames files and directories in a given folder recursively, removing a given string from filenames and directory names. It does not require any libraries to be installed.
Note that this script has been tested, however we can’t guarantee it won’t destroy some data under some conditions. Backup your data and use with caution(best to try using --dry --verbose
!)
These are the command line options it provides:
usage: RemoveFromNames.py [-h] [-c] [--dry] [-D] [-F] [-i] [-v] dir remove_string
Process and rename files and directories by removing a specific string.
positional arguments:
dir Input directory to scan recursively
remove_string String to remove from filenames and folder names
options:
-h, --help show this help message and exit
-c, --compress_spaces
Compress multiple spaces into one
--dry Dry run. Do not actually rename anything.
-D, --no_dirs Don't rename directories.
-F, --no_files Don't rename files.
-i, --case_insensitive
Perform case-insensitive compare and replace.
-v, --verbose Print what is being renamed.
Source code:
#!/usr/bin/env python3
import os
import argparse
def rename_files_in_directory(base_dir, remove_string, compress_spaces=False, dry_run=False, verbose=False, no_dirs=False, no_files=False, case_insensitive=False):
if case_insensitive:
def contains(sub, main):
return sub.lower() in main.lower()
def replace(source, target, string):
pattern = re.compile(re.escape(source), re.IGNORECASE)
return pattern.sub(target, string)
else:
contains = lambda sub, main: sub in main
replace = lambda source, target, string: string.replace(source, target)
# First, rename directories if not skipped by --no_dirs
if not no_dirs:
for dirpath, dirnames, _ in os.walk(base_dir, topdown=False):
for dirname in dirnames:
if contains(remove_string, dirname):
new_name = replace(remove_string, "", dirname)
if compress_spaces:
new_name = ' '.join(new_name.split())
new_name = new_name.strip()
if os.path.exists(os.path.join(dirpath, new_name)):
print(f"Cannot rename directory '{dirname}' to '{new_name}' in '{dirpath}' because a directory with the new name already exists.")
continue
if verbose:
print(f"Renaming directory '{dirname}' to '{new_name}' in '{dirpath}'")
if not dry_run:
os.rename(os.path.join(dirpath, dirname), os.path.join(dirpath, new_name))
# Then, rename files if not skipped by --no_files
if not no_files:
for dirpath, _, filenames in os.walk(base_dir):
for filename in filenames:
if contains(remove_string, filename):
new_name = replace(remove_string, "", filename)
if compress_spaces:
new_name = ' '.join(new_name.split())
new_name = new_name.strip()
if os.path.exists(os.path.join(dirpath, new_name)):
print(f"Cannot rename '{filename}' to '{new_name}' in '{dirpath}' because a file with the new name already exists.")
continue
if verbose:
print(f"Renaming file '{filename}' to '{new_name}' in '{dirpath}'")
if not dry_run:
os.rename(os.path.join(dirpath, filename), os.path.join(dirpath, new_name))
def main():
parser = argparse.ArgumentParser(description="Process and rename files and directories by removing a specific string.")
parser.add_argument("dir", type=str, help="Input directory to scan recursively")
parser.add_argument("remove_string", type=str, help="String to remove from filenames and folder names")
parser.add_argument("-c", "--compress_spaces", action="store_true", help="Compress multiple spaces into one")
parser.add_argument("--dry", action="store_true", help="Dry run. Do not actually rename anything.")
parser.add_argument("-D", "--no_dirs", action="store_true", help="Don't rename directories.")
parser.add_argument("-F", "--no_files", action="store_true", help="Don't rename files.")
parser.add_argument("-i", "--case_insensitive", action="store_true", help="Perform case-insensitive compare and replace.")
parser.add_argument("-v", "--verbose", action="store_true", help="Print what is being renamed.")
args = parser.parse_args()
rename_files_in_directory(args.dir, args.remove_string, args.compress_spaces, args.dry, args.verbose, args.no_dirs, args.no_files, args.case_insensitive)
if __name__ == "__main__":
main()