Last active
December 13, 2016 22:58
-
-
Save mtimkovich/af69f80e92947d0ee35d86752fefbdc5 to your computer and use it in GitHub Desktop.
Mass rename files with python
This file contains 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 | |
import argparse | |
from glob import glob | |
import os | |
import re | |
import sys | |
def parse_args(): | |
parser = argparse.ArgumentParser('Rename files using regex') | |
parser.add_argument('regex', | |
help="regex to apply to files (e.g. 's/regex/replace/')") | |
parser.add_argument('files', nargs='+', | |
help='files to modify') | |
parser.add_argument('-n', '--dry-run', action='store_true', | |
help="print outcome, don't rename") | |
parser.add_argument('-v', '--verbose', action='store_true', | |
help='verbose output') | |
parser.add_argument('-x', '--ignore-ext', action='store_true', | |
help='ignore file extensions') | |
parser.add_argument('-i', '--interactive', action='store_true', | |
help='prompt before overwriting') | |
return parser.parse_args() | |
def confirm(msg): | |
return input('{} [Y/n] '.format(msg)).lower() == 'y' | |
def error(*msg): | |
print(*msg, file=sys.stderr) | |
args = parse_args() | |
split = args.regex.split('/') | |
if len(split) != 4 or split[0] != 's': | |
error("Invalid regex: '{}'".format(args.regex)) | |
sys.exit(1) | |
_, search, replace, flags = split | |
flags = re.I if flags == 'i' else 0 | |
# This bit is for Windows, where wildcards aren't expanded | |
if any('*' in f for f in args.files): | |
files = [] | |
for f in args.files: | |
files += glob(f) | |
else: | |
files = args.files | |
for f in files: | |
if not os.path.exists(f): | |
error("No such file or directory: '{}'".format(f)) | |
continue | |
if args.ignore_ext: | |
f, ext = os.path.splitext(f) | |
output = re.sub(search, replace, f, flags=flags) | |
# Add extension back | |
if args.ignore_ext: | |
f += ext | |
output += ext | |
# No change, don't care | |
if f == output: | |
continue | |
# Check for conflicts in interactive mode | |
if (args.interactive and | |
not args.dry_run and | |
os.path.exists(output) and | |
not confirm('overwrite {}?'.format(output))): | |
continue | |
if args.dry_run or args.verbose: | |
print('{} -> {}'.format(f, output)) | |
if not args.dry_run: | |
os.rename(f, output) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment