Created
June 3, 2012 17:27
-
-
Save FichteFoll/2864277 to your computer and use it in GitHub Desktop.
A small script I use for batch-renaming files and/or folders with Regular Expressions
This file contains hidden or 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
# A list of dicts will be run over every file or directory in the "current" directory. | |
# TODO: | |
# - 'directory' option: Use specified dir as "parent" | |
# - 'subdirs' option: Scan through subdirs (don't play with self-refering Junctions, if that's even possible) | |
import os | |
import re | |
regs = [ | |
# dict( | |
# test=r'', # regexp to test whether a renaming should take place at all; optinal (usually not necessary) | |
# match=r'', # rexexp | |
# repl=r'', # string or function | |
# type='all' # or 'file' or 'dir'; optional | |
# num=3 # number of replacements; optional (usually not necessary) | |
# } | |
# examples: | |
# dict( | |
# match=r'^.*? - (?P<album>.*) \(.*?(?P<year>\d+)\)', | |
# repl=r'\g<year> - \g<album>', | |
# type='dir' | |
# ) | |
# dict( | |
# match=r'^(\[biribiri\])\s+(.*)', | |
# repl=r'\2 \1', | |
# type='dir' | |
# ) | |
dict( | |
match=r'(.*)', | |
repl=r'\1', | |
type='all' | |
) | |
] | |
print("Parsing regs...") | |
regs_count_old = len(regs) | |
# compile regexps | |
regex_class = re.compile(".").__class__ | |
compile_tuple = ('match', 'test') | |
reg_count = 0 | |
for reg in regs: | |
for key in compile_tuple: | |
if key in reg: | |
try: | |
reg[key] = re.compile(reg[key]) | |
except Exception as e: # re.error, TypeError | |
print(("\t[Error] regs[%d]%s:\n" + | |
"\t Unable to compile %r:\n" + | |
"\t [Errstr]: %s\n" + | |
"\t Removing...") | |
% (reg_count | |
, 'match' in reg | |
and ( | |
not isinstance(reg['match'], regex_class) | |
and " = `%s`" % reg['match'] # cast to string if necessary | |
or " = `%s`" % reg['match'].pattern | |
) or '' | |
, key | |
, e) | |
) | |
regs.remove(reg) | |
reg_count += 1 | |
# test dicts in 'regs' for validness | |
reg_count = -1 | |
for reg in regs: | |
reg_count += 1 | |
if 'match' not in reg: | |
print(("\t[Error] regs[%d]:\n" + | |
"\t 'match' not specified! Removing...") | |
% reg_count) | |
regs.remove(reg) | |
continue | |
if 'repl' not in reg: | |
print(("\t[Error] regs[%d] = `%s`:\n" | |
"\t 'repl' not specified! Removing...") | |
% (reg_count, reg['match'].pattern)) | |
regs.remove(reg) | |
continue | |
if 'type' in reg and reg['type'] not in ("all", "file", "dir"): | |
print(("\t[Error] regs[%d] = `%s`:\n" | |
"\t Value of 'type' is not valid! Assuming 'all'...") | |
% (reg_count, reg['match'].pattern)) | |
del reg['type'] | |
regs_count = len(regs) | |
print("Removed %d regs out of %d (%d left)" % (regs_count - regs_count, regs_count_old, regs_count)) | |
print("Starting with applying...") | |
# Do the renaming | |
matching_regs = 0 | |
reg_count = 0 | |
rename_count_total = 0 | |
for reg in regs: | |
print("Parsing regs[%s]: `%s`->%s..." | |
% (reg_count, | |
reg['match'].pattern, | |
'`' + reg['repl'] + '`' if not callable(reg['repl']) else 'function') | |
) | |
files = os.listdir() | |
rename_count = 0 | |
for filename in files: | |
# test 'type' | |
if 'type' in reg: | |
if os.path.isdir(filename): | |
if reg['type'] == "file": | |
continue | |
else: | |
if reg['type'] == "dir": | |
continue | |
# apply 'test' | |
if 'test' in reg and not reg['test'].search(filename): | |
continue | |
# the regex | |
new_filename = reg['match'].sub(reg['repl'], filename, reg.get('count', 0)) | |
if new_filename != filename: | |
print("\tRenaming `%s` to `%s`..." % (filename, new_filename)) | |
try: | |
os.rename(filename, new_filename) | |
except OSError as e: | |
print(("\t[Error] while renaming" | |
"\t [Errno]: %d, [Errstr]: %s") | |
% (filename, new_filename, | |
e.errno, e.strerror) | |
) | |
else: | |
rename_count += 1 | |
print("\tRenamed %d files or dirs" % rename_count) | |
matching_regs += rename_count > 0 | |
rename_count_total += rename_count | |
print("Renamed %d files or dirs in total" % rename_count_total) | |
print("%d regexps actually matched" % matching_regs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment