Advertisement
ChrisProsser

rename.py

Jun 28th, 2013
2,270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.71 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import os, webbrowser as wb, time, re, datetime as dt
  4. from Tkinter import Tk
  5. import tkFileDialog as fd
  6. Tk().withdraw() # to stop shell opening for Tkinter
  7. username = os.environ.get('username')
  8. path = None
  9. open_when_done = False
  10. err_log = os.path.join(os.getenv('dt'),'rename_error_log.txt') # append
  11.  
  12. # Globals
  13. g_sort_type = 'NATURAL' # options allowed for DATE or NATURAL i.e. how Windows would sort by default
  14.  
  15. def write_log_file(file_history, reverted=False):
  16.     fname = str(username+'_'+str(dt.datetime.today())[:19]+'.csv').replace(':','-')
  17.     logfile = os.path.join(os.environ.get('logs'), 'rename', fname.replace(' ','_'))
  18.     f = open(logfile, 'w')
  19.     if reverted:
  20.         f.write('These files were reverted!!!\n')
  21.     f.write('Filename, Old Name, New Name\n')
  22.     for row in file_history:
  23.         f.write(str(str(row[0])+', '+row[1]+', '+row[2]+'\n'))
  24.     f.close()
  25.  
  26. def revert(file_history):
  27.     for row in file_history:
  28.         new_name = row[2]
  29.         old_name = row[1]
  30.         print '...reverting file', new_name, 'to', old_name
  31.         os.rename(os.path.join(path,new_name), os.path.join(path,old_name))
  32.  
  33. def get_range(specific, file_list, excl_list):
  34.     count = len(file_list)
  35.    
  36.     #find a zero based index range (which goes upto but not including the upper limit)
  37.     if specific == 'Y':
  38.         print '\n'
  39.         print 'Please specify the name of the file you want to start from, you do not need to'
  40.         print 'write the full name, just enough characters for the input to be unique e.g. if'
  41.         print 'two files are called "P30687" and "P30799", a single file could be identifed by'
  42.         print 'entering "P306".\n'
  43.         print 'You can leave either the start filename or end filename empty.'
  44.  
  45.         c = 0
  46.         while c <> 1:
  47.             c, tmp = 0, None
  48.             print '\n','Range Start:'
  49.             print '-----------'
  50.             first = raw_input('Please enter the file to start from: ').lower()
  51.             if not first:
  52.                 start = 0
  53.                 break
  54.             for name in file_list:
  55.                 if first in name.lower():
  56.                     if not tmp:
  57.                         tmp = name
  58.                     c += 1
  59.             if c == 0:
  60.                 print 'No matches were found for string:', first, ', please try again...'
  61.             elif c > 1:
  62.                 print 'More than one file found, do you want to start from the first: '+tmp
  63.                 if raw_input('(Y/N?): ').upper() == 'Y':
  64.                     start, c = file_list.index(tmp), 1
  65.                 else:
  66.                     'Okay, please give a more specific name.\n'
  67.             else:
  68.                 start = file_list.index(tmp)
  69.    
  70.         c = 0
  71.         while c <> 1:
  72.             c, tmp = 0, None
  73.            
  74.             print '\n','Range End:'
  75.             print '---------'
  76.             last = raw_input('Please enter the last file to be included: ').lower()
  77.             if not last:
  78.                 end = count
  79.                 break
  80.             for name in file_list:
  81.                 if last in name.lower():
  82.                     if not tmp:
  83.                         tmp = name
  84.                     c += 1
  85.             if c == 0:
  86.                 print 'No matches were found for string:', last, ', please try again...'
  87.             elif c > 1:
  88.                 print 'More than one file found, do you want to start from the first: '+tmp+' (Y/N?):'
  89.                 if raw_input('> ').upper() == 'Y':
  90.                     last, c = file_list.index(tmp)+1, 1
  91.                 else:
  92.                     'Okay, please give a more specific name.\n'
  93.             else:
  94.                 end = file_list.index(tmp)+1
  95.                    
  96.     else:
  97.         start, end = 0, count
  98.  
  99.     return start, end, count
  100.  
  101. def make_excl_list():
  102.     finished = False
  103.     lst = []
  104.     print '\n'
  105.     print 'You will now be prompted for any text strings that you want to exclude from the'
  106.     print 'renaming process. Please notes that these are not case sensitive i.e. "mar"'
  107.     print 'would exclude any file names containing "MAR" or "Mar" etc. \n'
  108.    
  109.     while not finished:
  110.         lst.append(raw_input('Enter exclusion text: ').lower())
  111.         if raw_input('Do you want to add any more? (Y/N): ').upper()[0] == 'N':
  112.             finished = True
  113.     return lst
  114.  
  115. def rename_files(file_list, file_type):
  116.     happy = False
  117.     excl_list = []
  118.  
  119.     while not happy:
  120.         print 'No of Digits:'
  121.         print '------------'
  122.         print 'How many digits do you want to use for the numbering e.g. 3 for 001 - 999'
  123.         no_of_digits = int(raw_input('> '))
  124.        
  125.         print '\n', 'Start No:'
  126.         print '--------'
  127.         if raw_input('Do you want to start from 1? (Y/N): ').upper() == 'Y':
  128.             file_no = 1
  129.         else:
  130.             file_no = int(raw_input('Please enter the number that you want to start from: '))
  131.  
  132.        
  133.         print '\n', 'Exclusions:'
  134.         print '----------'
  135.         print 'Do you want to specify any exclusions (i.e. files to be left unchanged) (Y/N)?'
  136.         excl = raw_input('> ').upper()
  137.  
  138.         if excl == 'Y':
  139.             excl_list = make_excl_list()
  140.  
  141.         print '\n', 'Range:'
  142.         print '-----'
  143.         print 'Do you want to specify a range of filenames to be renamed (Y/N)?'
  144.         rnge = raw_input('> ').upper()
  145.         start, end, count = get_range(rnge, file_list, excl_list)
  146.  
  147.         print '\n', 'Prefix:'
  148.         print '------'
  149.         print 'Please enter the prefix that you want to use before the numbers (can be empty)'
  150.         prefix = raw_input('> ')
  151.        
  152.         print '\n', 'Suffix:'
  153.         print '------'
  154.         print 'Please enter the suffix that you want to use after the numbers (can be empty)'
  155.         print 'For a special suffix of _ and the month the file was last modified enter _mon'
  156.         suffix = raw_input('> ')
  157.  
  158.         l = len(str(file_no))
  159.         eg = prefix+'0'*(no_of_digits-l)+str(file_no)+suffix+' to '+prefix+'9'*no_of_digits+suffix
  160.         print '\n', 'Naming schema set to:', eg
  161.  
  162.         print '\n', 'Proceed?'
  163.         print '-------'
  164.         if raw_input('Are you happy to proceed? (Y/N): ').upper() == 'Y':
  165.             happy = True
  166.         else:
  167.             if raw_input('Do you want to change directory? (Y/N): ').upper() == 'Y':
  168.                 return False
  169.             else:
  170.                 print 'Okay, we can go through the instructions again for the current directory\n'
  171.    
  172.     file_history = [] # contains a row per file with (file_no, old_name, new_name)
  173.  
  174.     print '\n', (end - start), file_type, 'files found wuthin range.'
  175.     if raw_input('Do you want to rename these files? (Y/N): ').upper() == 'Y':
  176.         print '\n', 'Starting renaming process...', '\n'
  177.  
  178.         # loop through specified range within file_list
  179.         for n in range(start,end):
  180.             excluded = False
  181.             if excl == 'Y':
  182.                 for ex in excl_list:
  183.                     if ex in file_list[n].lower():
  184.                         excluded = True
  185.                         print '***leaving file', file_list[n], 'because of exclusion:', ex
  186.            
  187.             if not excluded:        
  188.                 if suffix == '_mon':
  189.                     use_suffix = '_'+time.ctime(os.path.getmtime(os.path.join(path, file_list[n])))[4:7]
  190.                 else:
  191.                     use_suffix = suffix
  192.                 l = len(str(file_no))
  193.                 ext = file_list[n][file_list[n].rfind('.'):].lower()
  194.                 new_name = prefix+'0'*(no_of_digits-l)+str(file_no)+use_suffix+ext
  195.                 file_history.append((file_no, file_list[n], new_name))
  196.                 print '...renaming file', file_list[n], 'to', new_name
  197.                 os.rename(os.path.join(path,file_list[n]), os.path.join(path,new_name))
  198.                 file_no += 1
  199.         if open_when_done:
  200.             print '\n', 'Opening directory...', '\n'
  201.             wb.open(path)
  202.     else:
  203.         return False
  204.  
  205.     print 'The files have now been re-named. However, a record has been taken of the old'
  206.     print 'file names so that they can be reverted if required.','\n'
  207.  
  208.     if raw_input('Are you happy with the changes? (Y/N): ').upper() == 'Y':
  209.         write_log_file(file_history, False)
  210.         return True
  211.     else:
  212.         if raw_input('Do you want to revert to the old file name? (Y/N): ').upper() == 'Y':
  213.             revert(file_history)
  214.             write_log_file(file_history, True)
  215.             print '\n', 'The files should now be restored to their original names'
  216.         return True
  217.  
  218. def sort_list(l):
  219.     if g_sort_type.upper() == 'DATE':
  220.         file_date_tuple_list, sorted_files = [], []
  221.        
  222.         for i in l:
  223.             d = os.path.getmtime(os.path.join(path,i))
  224.             file_date_tuple = (i,d)
  225.             file_date_tuple_list.append(file_date_tuple)
  226.            
  227.         file_date_tuple_list.sort(key=lambda x: x[1])
  228.        
  229.         for i in file_date_tuple_list:
  230.             sorted_files.append(i[0])
  231.         return sorted_files
  232.     else:
  233.         convert = lambda text: int(text) if text.isdigit() else text.lower()
  234.         alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
  235.         return sorted(l, key = alphanum_key)
  236.  
  237. def get_file_extensions(file_type):
  238.     if file_type == 'image':
  239.         lst = [
  240.             '.bmp',  #Bitmap Image File
  241.             '.dds',  #DirectDraw Surface
  242.             '.dng',  #Digital Negative Image File
  243.             '.gif',  #Graphical Interchange Format File
  244.             '.jpg',  #JPEG Image
  245.             '.png',  #Portable Network Graphic
  246.             '.psd',  #Adobe Photoshop Document
  247.             '.pspimage', #PaintShop Pro Image
  248.             '.tga',  #Targa Graphic
  249.             '.thm',  #Thumbnail Image File
  250.             '.tif',  #Tagged Image File
  251.             '.yuv',  #YUV Encoded Image File
  252.             '.mov',      #Movie File
  253.             '.avi',    
  254.             '.mp4'
  255.             ]  
  256.     return lst
  257.  
  258. def make_list():
  259.     selected = False
  260.  
  261.     while not selected:
  262.         # Date or natural sort used to order contents as Windows does
  263.         content = sort_list(os.listdir(path))
  264.         print '\n', 'The current directory selected is:','\n', path,'\n'
  265.  
  266.         file_type = 'image'
  267.         ext_list = get_file_extensions(file_type)
  268.         file_list = []
  269.         for name in content:
  270.             if name[name.rfind('.'):].lower() in ext_list:
  271.                 file_list.append(name)
  272.         print ''
  273.        
  274.         if len(file_list) == 0:
  275.             print 'No image files have been found', '\n'
  276.         else:
  277.             selected = rename_files(file_list, file_type)
  278.     return path
  279.  
  280. def get_dir():
  281.     global path
  282.     tmp_path, pict = None, None
  283.     computer = os.environ.get('computername')
  284.  
  285.     if computer.lower() == 'prosser-pc':
  286.         if os.getenv('username').lower() == 'rachel.prosser':
  287.             pict = os.path.join('E:\Users', os.getenv('username'), 'Pictures', 'Family Photos')
  288.         else:
  289.             pict = os.path.join('E:\Users', os.getenv('username'), 'Pictures')
  290.     else:
  291.         pict = os.path.join(os.environ.get('userprofile'), 'Pictures')
  292.  
  293.     # start user from relevant pictures directory...
  294.     os.chdir(pict)
  295.  
  296.     while not path:
  297.         # if tmp_path assigned at end of previous loop use this, otherwise prompt for dir...
  298.         if tmp_path:
  299.             path = tmp_path
  300.             tmp_path = None
  301.         else:
  302.             print 'Please select a directory to rename images...', '\n'
  303.             path = fd.askdirectory()
  304.  
  305.         # false is returned if something goes wrong causing the loop to continue
  306.         path = make_list()
  307.  
  308.         if raw_input('Do you want to Continue? (Y\N): ').upper() == 'Y':
  309.             if raw_input('Do you want to use the same directory again? (Y\N): ').upper() == 'Y':
  310.                 tmp_path = path #store to use in next loop
  311.             path = None #this will cause the loop to continue
  312.  
  313. def main():
  314.     print 'Program written by Chris Prosser for his beloved wife Rachel.', '\n'
  315.     print 'This program allows the user to select a directory and rename all of the files'
  316.     print 'of a given type within that directory.', '\n'
  317.  
  318.     try:
  319.         get_dir()
  320.     except NameError:
  321.         exc_type, exc_value, exc_traceback = sys.exc_info()
  322.         lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
  323.         print 'An error occurred, the details shown below will be written to an error log file:'
  324.         print err_log
  325.         print ''.join('!! ' + line for line in lines)
  326.         with open(err_log, "a") as myfile:
  327.             myfile.write(''.join('!! ' + line for line in lines))
  328.     else:
  329.         print '\n', '*** PROCESS COMPLETE ***'
  330.  
  331. if __name__ == '__main__':
  332.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement