Attachment 'rename.py'

Download

   1 #!/usr/bin/env python
   2 #
   3 # Rename files.
   4 #
   5 
   6 import sys, os, shutil, getopt, time, traceback
   7 
   8 
   9 class MyException(Exception):
  10     __DEFAULT_MESSAGE = "Error: Default error message."
  11 
  12     def __init__(self, msg=__DEFAULT_MESSAGE):
  13         self.__message = msg
  14 
  15     def __str__(self):
  16         return repr(self.__message)
  17 
  18     def getMessage(self):
  19         return self.__message
  20 
  21 
  22 class Rename:
  23     def __init__(self, cliOpts):
  24         if cliOpts == None:
  25             raise TypeError
  26 
  27         # Get the command line arguments.
  28         self.__incomingPath = cliOpts.get('-i')
  29         self.__destinationPath = cliOpts.get('-d')
  30         self.__filePatternOld = cliOpts.get('-o')
  31         self.__filePatternNew = cliOpts.get('-n')
  32         self.__startSequence = int(cliOpts.get('-s'))
  33         self.__endSequence = int(cliOpts.get('-e'))
  34         self.__newSequence = int(cliOpts.get('-r'))
  35         self.__debug = cliOpts.get('-D')
  36         self.__noop = cliOpts.get('-N')
  37         self.__renameFlag = cliOpts.get('-R')
  38         self.__skipFiles = cliOpts.get('-S')
  39 
  40     def start(self):
  41         """
  42         Starts the process.
  43         """
  44         format = "%a %b %d %H:%M:%S %Z %Y"
  45 
  46         if self.__debug:
  47             print "Start time: %s" % time.strftime(format,
  48                                                    time.localtime(time.time()))
  49         # Do it here
  50         self.__checkDirectories()
  51         self.__sanityChecks()
  52         self.__rename()
  53 
  54         if self.__debug:
  55             print "End time: %s" % time.strftime(format,
  56                                                  time.localtime(time.time()))
  57 
  58     def __checkDirectories(self):
  59         """
  60         Prepare the file list.
  61         """
  62         try:
  63             if not os.path.isdir(self.__destinationPath):
  64                 print "Do you want to make this path? %s [y/n]:" % \
  65                       self.__destinationPath,
  66                 response = sys.stdin.readline()
  67 
  68                 if response.upper()[0:1] == "Y":
  69                     os.mkdir(self.__destinationPath, 0755)
  70                 else:
  71                     msg = "Cannot proceed without a destination directory."
  72                     raise MyException(msg)
  73         except OSError, e:
  74             msg = str(e)
  75             raise MyException(msg)
  76 
  77     def __sanityChecks(self):
  78         """
  79         Do some checking of command line arguments.
  80         """
  81         # Find the high value of the new sequence.
  82         lowOldSeq = int(self.__startSequence)
  83         highOldSeq = int(self.__endSequence)
  84         lowNewSeq = int(self.__newSequence)
  85         highNewSeq = lowNewSeq + (highOldSeq - lowOldSeq)
  86         lengthOld  = self.__filePatternOld.count("\\n")
  87         # Find length of new sequence.
  88         lengthNew = self.__filePatternNew.count("\\n")
  89         #print self.__filePatternOld, len(str(highOldSeq)), lengthOld, \
  90         #      self.__filePatternNew, len(str(highNewSeq)), lengthNew
  91 
  92         if len(str(highOldSeq)) > lengthOld:
  93             msg = "Old pattern does not allow given end sequence number"
  94             raise MyException(msg)
  95 
  96         if len(str(highNewSeq)) > lengthNew:
  97             msg = "New pattern does not allow highest sequence number"
  98             raise MyException(msg)
  99 
 100     def __rename(self):
 101         """
 102         Rename all files based on the incoming and destination pattern.
 103         """
 104         diff = self.__newSequence - self.__startSequence
 105         ranges = range(self.__startSequence, self.__endSequence + 1)
 106 
 107         if diff >= 0:
 108             ranges.reverse()
 109         #print ranges, "Number in ranges:", len(ranges)
 110 
 111         for seq in ranges:
 112             newSeq = seq + diff
 113             newfile = self.__makeFilename(self.__filePatternNew, newSeq)
 114             newFilename = os.path.join(self.__destinationPath, newfile)
 115             #print newFilename
 116 
 117             if os.path.isfile(newFilename):
 118                 msg = "The file %s exists, cannot proceed!!" % newFilename
 119                 raise MyException(msg)
 120 
 121             oldFilename = self.__makeFilename(self.__filePatternOld, seq)
 122             #print oldFilename
 123 
 124             if not os.path.isfile(oldFilename):
 125                 msg = "The file %s does not exists, " % oldFilename
 126 
 127                 if self.__skipFiles:
 128                     msg += "however skip is set so continuing."
 129                 else:
 130                     msg += "cannot proceed with renaming files."
 131 
 132                 if self.__debug: print "%s" % msg
 133                 if self.__skipFiles: continue
 134                 raise MyException(msg)
 135             
 136             if not self.__noop:
 137                 try:
 138                     shutil.copyfile(oldFilename, newFilename)
 139 
 140                     # Delete old file if renaming flag is set.
 141                     if self.__renameFlag:
 142                         os.unlink(oldFilename)
 143                 except (OSError, IOError), e:
 144                     msg = "Could not rename %s to %s, %s" % \
 145                           (oldFilename, newFilename, e)
 146                     raise MyException(msg)
 147 
 148             if self.__noop or self.__debug:
 149                 flagMap = {'debug': self.__debug,
 150                            'noop': self.__noop,
 151                            'rename': self.__renameFlag,
 152                            'skip': self.__skipFiles}
 153                 msg = "WARNING -- Flags set: "
 154                 flagList = [" %s: %s" % (k, v) for k,v in flagMap.items()]
 155                 msg += ', '.join(flagList)
 156                 msg += ", source file: %s, destination file: %s\n" % \
 157                        (oldFilename, newFilename)
 158                 print msg
 159 
 160     def __makeFilename(self, pattern, seq):
 161         """
 162         Make the file name.
 163 
 164         Arguments:
 165         seq  -- The sequence number.
 166         Returns:
 167         A string representing the filename.
 168         """
 169         length = pattern.count("\\n")
 170         sequence = str(seq).zfill(length)
 171         start = pattern.find("\\n")
 172         base = pattern[0:start]
 173         end = pattern.rfind("\\n") + 2
 174         ext = pattern[end:]
 175         return "%s%s%s" % (base, sequence, ext)
 176 
 177 
 178 class GetOptions:
 179     """
 180     This class parses the command line options and returns a dictionary
 181     of {option:value, ...} pairs.
 182     """
 183     def __init__(self, args=None, options=None):
 184         """
 185         Parse the option list.
 186         """
 187         self.args = args
 188         self.options = options
 189         self.optmap = {}
 190 
 191     def parseOptions(self):
 192         optlist, extraopts = getopt.getopt(self.args, self.options)
 193         return self._createDict(optlist)
 194 
 195     def _createDict(self, opts):
 196         """
 197         Create a dictionary of command line flags.
 198         """
 199         for i in opts:
 200             if i[1]:
 201                 self.optmap[i[0]] = i[1]
 202             else:
 203                 self.optmap[i[0]] = 1
 204         return self.optmap
 205 
 206     def getOptionMap(self):
 207         """
 208         Gets the option dictionary map.
 209         """
 210         return self.optmap
 211 
 212 
 213 ######################################################################
 214 # Unbound functions
 215 ###################
 216 def usage():
 217     print "Usage: %s " % (sys.argv[0]) + "-[DNRS] " + \
 218           "-[i Incoming path, d Destination path, " + \
 219           "o 'File pattern old', n 'File pattern new', " + \
 220           "s Start sequence, e End sequence, r New sequence start]"
 221 
 222 
 223 ######################################################################
 224 # Start execution here.
 225 #######################
 226 if __name__ == "__main__":
 227     options = 'DNRSi:d:o:n:s:e:r:'
 228     opts = None
 229 
 230     try:
 231         optObj = GetOptions(sys.argv[1:], options)
 232         opts = optObj.parseOptions()
 233     except:
 234         print "Error: Invalid argument list."
 235         usage()
 236         sys.exit(1)
 237 
 238     # Incoming path
 239     if not opts.has_key('-i'):
 240         usage()
 241         sys.exit(1)
 242 
 243     # Destination path
 244     if not opts.has_key('-d'):
 245         opts['-d'] = opts.get('-i')
 246 
 247     # File pattern old
 248     if not opts.has_key('-o'):
 249         usage()
 250         sys.exit(1)
 251 
 252     # File pattern new
 253     if not opts.has_key('-n'):
 254         opts['-n'] = opts.get('-o')
 255 
 256     # Start sequence
 257     if not opts.has_key('-s'):
 258         usage()
 259         sys.exit(1)
 260 
 261     # End sequence
 262     if not opts.has_key('-e'):
 263         usage()
 264         sys.exit(1)
 265 
 266     # New sequence start
 267     if not opts.has_key('-r'):
 268         usage()
 269         sys.exit(1)
 270 
 271     # Rename option
 272     if opts.has_key('-R'):
 273         opts['-R'] = True
 274     else:
 275         opts['-R'] = False
 276 
 277     # Skip missing files--default is True
 278     if opts.has_key('-S'):
 279         opts['-S'] = False
 280     else:
 281         opts['-S'] = True
 282 
 283     # NOOP option
 284     if opts.has_key('-N'):
 285         opts['-N'] = True
 286     else:
 287         opts['-N'] = False
 288 
 289     # Debug option
 290     if opts.has_key('-D'):
 291         opts['-D'] = True
 292         print "Debug: Command line options: ", opts
 293     else:
 294         opts['-D'] = False
 295 
 296     ts = None
 297 
 298     try:
 299         ts = Rename(cliOpts=opts)
 300         ts.start()
 301     except MyException, e:
 302         print e.getMessage()
 303         usage()
 304 
 305         if opts.has_key('-D'):
 306             tb = sys.exc_info()[2]
 307             traceback.print_tb(tb)
 308             print "%s: %s\n" % (sys.exc_info()[0], sys.exc_info()[1])
 309 
 310         sys.exit(1)
 311 
 312     sys.exit(0)

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.