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.