MMV/mmv
2025-08-10 16:48:41 -04:00

59 lines
2.9 KiB
Python
Executable file

#! /usr/bin/env python
"""mmv: Multiple move.
A small utility designed to rename files in the current working directory both matching against, and transforming the matches via python regular expressions."""
import re,os,os.path,sys,optparse
class OptParser(optparse.OptionParser):
def format_epilog(self,formatter):
return self.epilog
parser = OptParser(usage="%prog [OPTIONS] $regex_match [$lambda | $str_method | $regex_sub]",version="%prog 0.9.7.1")
parser.set_description(__doc__)
parser.add_option("-l","--lambda",action="store_true",default=False,dest="_lambda",help="Use a lambda expression. Match file names against $regex_match, transform with eval('lambda fname:' + $lambda).")
parser.add_option("-r","--regex",action="store_true",default=True,dest="_regex",help="(Default) Use regexs. Match file names with $regex_match, transform with $regex_sub.")
parser.add_option("-s","--string",action="store",default=False,dest="_string",help="Use a python string method to transform file names.")
parser.add_option("-t","--test",action="store_true",default=False,dest="_test",help="Test. Display all output but do not commit new filenames.")
parser.add_option("-v","--verbose",action="store_true",default=False,dest="_verbose",help="Verbose. Display output, implied by -t")
parser.epilog = """Examples:
mmv -t "mmmv" "mmv" #convert all cases of 'mmmv' to 'mmv'
mmv -tl "." "'%s.%s' % ('.'.join(fname.split('.')[:-1]),fname.split('.')[1:].upper())" #capitalize file extensions
mmv -tl "open(fname,'r').readline().replace(' ','_')" #use first line of the file for new filename
mmv -t --string upper #return uppercase filenames
"""
(options,args) = parser.parse_args()
try:
regex = re.compile(args[0])
except Exception as E:
parser.error("Missing or malformed filename matching regex")
raise
if options._test:
mmv = lambda src,dst: "testing:%s:\t%s" % (src,dst) #dummy
options._verbose = True #always dump testing output
else:
mmv = lambda src,dst: os.rename(src,dst) #default behavior
if options._lambda: #user supplied func. uses eval; treat with care
trans = eval('lambda fname: %s' % args[1])
elif options._string:
trans = lambda src: getattr(src,options._string)()
else:
trans = lambda src: regex.sub(args[1],src) #default, simple regex sub
for ix in os.listdir('./'): #cwd only
if regex.search(ix):
try:
dst = trans(ix)
result = mmv(ix,dst)
if result == None:
result = "%s:\t%s" % (ix,dst)
except Exception as e:
result = e.__doc__
if options._verbose:
print(result)