diff --git a/tren.py b/tren.py index 69c8367..d2c0452 100755 --- a/tren.py +++ b/tren.py @@ -8,7 +8,7 @@ PROGNAME = "tren.py" BASENAME = PROGNAME.split(".py")[0] PROGENV = BASENAME.upper() -RCSID = "$Id: tren.py,v 1.146 2010/02/05 19:20:25 tundra Exp $" +RCSID = "$Id: tren.py,v 1.147 2010/02/05 21:13:07 tundra Exp $" VERSION = RCSID.split()[2] # Copyright Information @@ -83,10 +83,12 @@ ##### ALL = "All" # Rename target is whole filename +ARROW = "--->" # Used for formatting renaming messages COMMENT = "#" # Comment character in include files DEFEXT = "." # Default name/extension separator DEFLEN = 80 # Default output line length DEFSEP = "=" # Default rename command separator: old=new +DEFSUFFIX = ".backup" # String used to rename existing targets ESC = "\\" # Escape character EXT = "Ext" # Rename target is extension INCL = "I" # Include file command line option @@ -98,6 +100,7 @@ DEBUG = "DEBUG" CASESENSITIVE = "CASESENSITIVE" ERRORCONTINUE = "ERRORCONTINUE" +EXISTSUFFIX = "EXISTSUFFIX" EXTDELIM = "EXTDELIM" FORCERENAM = "FORCERENAM" GLOBAL = "GLOBAL" @@ -174,9 +177,11 @@ ##### -# Warning Messages +# Informational Messages ##### +iSKIPPING = "Skipping renaming of '%s' - Newname '%s' Exists!" + ##### # Usage Prompts @@ -184,26 +189,27 @@ uTable = [PROGVER, HOMEPAGE, - "usage: " + PROGNAME + " [-abCcdEefGghqtvwXx] [-I file] [-l string] [-r old=new]... file|dir file|dir ...", + "usage: " + PROGNAME + " [-abCcdEefGghqtvwXx] [-I file] [-l string] [-r old=new]... [-S suffix] file|dir file|dir ...", " where,", " -a Rename within the entire file or directory name (Default)", " -C Do case-sensitive renaming (Default)", - " -c Collapse case when doing string substitution.", + " -c Collapse case when doing string substitution", " -d Dump debugging information", - " -e Only perform renaming within extension portion of or directory name.", + " -e Only perform renaming within extension portion of or directory name", " -E Continue renaming even after an error is encountered", - " -f Force renaming even if target file or directory name already exists.", + " -f Force renaming even if target file or directory name already exists", " -G Rename only the first instance of the specified string (Default)", - " -g Replace all instances (global rename) of the old string with the new.", - " -h Print help information.", + " -g Replace all instances (global rename) of the old string with the new", + " -h Print help information", " -I file Include command line arguments from file", - " -l string File extension delimiter string. (Default: .)", - " -q Quiet mode, do not show progress.", - " -R rensep Separator string for -r rename arguments. (Default: =)", - " -r old=new Replace old with new in file or directory names.", + " -l string File extension delimiter string (Default: %s)" % DEFEXT, + " -q Quiet mode, do not show progress", + " -R rensep Separator string for -r rename arguments (Default: %s)" % DEFSEP, + " -r old=new Replace old with new in file or directory names", + " -S suffix Suffix to use when renaming existing filenames (Default: %s)" % DEFSUFFIX, " -t Test mode, don't rename, just show what the program *would* do", - " -v Print detailed program version information and exit.", - " -w Line length of diagnostic and error output (Default: 75)", + " -v Print detailed program version information and exit", + " -w Line length of diagnostic and error output (Default: %s)" % DEFLEN, " -X Treat the renaming strings literally (Default)", " -x Treat the old replacement string as a Python regular expression", ] @@ -221,6 +227,7 @@ DEBUG : False, # Debugging off CASESENSITIVE : True, # Search is case-sensitive ERRORCONTINUE : False, # Do not continue after error + EXISTSUFFIX : DEFSUFFIX, # What to tack on when renaming existing targets EXTDELIM : DEFEXT, # Name/Extension delimiter FORCERENAM : False, # Do not rename if target already exists GLOBAL : False, # Only rename first instance of old string @@ -497,6 +504,7 @@ # operation RenamingError = False + newname = pathname + basename # First make sure the new name meets length constraints @@ -508,8 +516,34 @@ ErrorMsg(eNAMELONG % (target, basename, MAXNAMELEN), EXIT=not ProgramOptions[ERRORCONTINUE]) RenamingError = True - if not RenamingError: - print ColumnPad([target, pathname + basename], padwidth = 50) + if (target != newname) and not RenamingError: + + # Figure out if the newname already exists + + newexists = False + if os.path.exists(newname): + newexists = True + + # Just show what we would do + + if ProgramOptions[TESTMODE]: + + if newexists: + if ProgramOptions[FORCERENAM]: + + renameexisting = newname + ProgramOptions[EXISTSUFFIX] + InfoMsg(ColumnPad([newname + " %s " % ARROW, renameexisting]), TESTMODE) + + else: + + InfoMsg(iSKIPPING % (target, newname), TESTMODE) + + InfoMsg(ColumnPad([target + " %s " % ARROW, newname]), TESTMODE) + + # Actually do the renaming + else: + + print target + "---->"+ newname # End of 'Rename()' @@ -543,12 +577,12 @@ # Turn A List Into Columns With Space Padding ##### -def ColumnPad(list, padchar=PADCHAR, padwidth=PADWIDTH): +def ColumnPad(list, PAD=PADCHAR, WIDTH=PADWIDTH): retval = "" for l in list: l = str(l) - retval += l + ((padwidth - len(l)) * padchar) + retval += l + ((WIDTH - len(l)) * PAD) return retval @@ -560,8 +594,8 @@ ##### def ConditionLine(msg, - padchar=PADCHAR, \ - padwidth=PADWIDTH, \ + PAD=PADCHAR, \ + WIDTH=PADWIDTH, \ wrapindent=WRAPINDENT ): retval = [] @@ -569,7 +603,7 @@ msg = msg[ProgramOptions[MAXLINELEN]:] while msg: - msg = padchar * (padwidth + wrapindent) + msg + msg = PAD * (WIDTH + wrapindent) + msg retval.append(msg[:ProgramOptions[MAXLINELEN]]) msg = msg[ProgramOptions[MAXLINELEN]:] @@ -598,7 +632,7 @@ def DumpList(handler, msg, listname, content): handler(msg) - itemarrow = ColumnPad([listname, " "], padwidth=LSTPAD) + itemarrow = ColumnPad([listname, " "], WIDTH=LSTPAD) handler(ColumnPad([" ", " %s %s" % (itemarrow, content)])) # End of 'DumpList()' @@ -684,11 +718,25 @@ ##### +# Print An Informational Message +##### + +def InfoMsg(dmsg, msgtype): + + l = ConditionLine(dmsg) + + for dmsg in l: + PrintStdout(PROGNAME + " " + msgtype + ": " + dmsg) + +# End of 'InfoMsg()' + + +##### # Print To stderr ##### -def PrintStderr(msg, trailing="\n"): - sys.stderr.write(msg + trailing) +def PrintStderr(msg, TRAILING="\n"): + sys.stderr.write(msg + TRAILING) # End of 'PrintStderr()' @@ -697,8 +745,8 @@ # Print To stdout ##### -def PrintStdout(msg, trailing="\n"): - sys.stdout.write(msg + trailing) +def PrintStdout(msg, TRAILING="\n"): + sys.stdout.write(msg + TRAILING) # End of 'PrintStdout' @@ -855,7 +903,7 @@ # And parse the command line try: - opts, args = getopt.getopt(OPTIONS, 'abbCcdEefGghl:qR:r:tvw:Xx]') + opts, args = getopt.getopt(OPTIONS, 'abbCcdEefGghl:qR:r:S:tvw:Xx]') except getopt.GetoptError as e: ErrorMsg(eBADARG % e.args[0], EXIT=True) @@ -922,6 +970,9 @@ req[opt] = ProgramOptions[opt] targs.RenRequests.append(req) + if opt == "-S": + ProgramOptions[EXISTSUFFIX] = val + if opt == "-t": ProgramOptions[TESTMODE] = True