Blame | Last modification | View Log | RSS feed
#!/usr/bin/pythonimport sys, os, glob, re, shutilDICT_FILE = os.path.expanduser('~/bin/animesorter.dict')WORK_DIR = os.path.expanduser('~/downloads/usenet')SORT_DIR = '/data/Anime'def parsedict(dict=DICT_FILE):"""Parses a dictionary file containing the sort definitions in the form:DIRECTORY = PATTERNReturns a list of tuples, each containing the contents of one line."""try:f = open(dict, 'r', 0)try:data = f.read()finally:f.close()except IOError:print 'Error opening %s ... exiting!' % dictsys.exit()### Get a LIST containing each line in the filelines = [l for l in data.split('\n') if len(l) > 0]### Split each line into a tuple, and strip each element of spacestuples = [(k, v) for k, v in [l.split('=') for l in lines]]tuples = [(k.strip() ,v.strip()) for k, v in tuples]return tuple(tuples)def getfiles(dir=WORK_DIR):"""getfiles(dir):dir is type STRINGReturn a LIST of the files of type *.{avi,ogm,mkv} that are in thedirectory given as a parameter."""files = []types = ('avi', 'ogm', 'mkv')# Match every type in the type arrayfor t in types:files.extend( glob.glob('%s/%s' % (dir, '*.%s' % t)) )files = [f for d,f in [os.path.split(f) for f in files]]return filesdef getdirs(dir=WORK_DIR):"""getdirs(dir):dir is type STRINGReturn a LIST of the subdirectories of the directory given as a parameter."""dirs = [os.path.join(dir, d) for d in os.listdir(dir) if os.path.isdir(os.path.join(dir, d))]return dirsdef createpattern(string):"""createpattern(string):Returns a sre.SRE_Pattern created from the string given as a parameter."""pattern = re.compile(string)return patterndef getmatches(files, pattern):"""getmatches(files, pattern):files is type LISTpattern is type sre.SRE_PatternReturns a list of the files matching the pattern as type sre.SRE_Match."""matches = [m for m in files if pattern.search(m)]return matchesdef fname_from_match(match):"""fname_from_match(match):match is a LIST containing type sre.SRE_MatchReturns a string (the filename) of the LIST match given as a parameter."""fname = ''.join(match.string)return fnamedef getmatchnames(matches):"""getmatchnames(matches):matches is a String containing (many) objects of type sre.SRE_MatchReturns a LIST of STRINGS representing the filenames of the matches."""matchnames = [fname_from_match(n) for n in matches]return matchnamesdef move_file(file, fromdir=WORK_DIR, todir=SORT_DIR):"""move_file(file, dir):file is a STRING representing a complete filename (with full path)fromdir is a STRING representing where the file exists currentlydestdir is a STRING representing the directory to move the file toReturns either True if the move was successful, False otherwise."""fromfile = os.path.join(fromdir, file)destfile = os.path.join(todir, file)try:shutil.move(fromfile, destfile)except:return Falsereturn Truedef get_dstdir(dir):"""get_dstdir(dir):Get an appropriate destination directory depending on whether dirhas a slash on the beginning"""if( dir[0] == '/' ):return dirreturn os.path.join(SORT_DIR, dir)def printfailed(moved, failed):"""printfailed(moved, failed):moved is an INTEGER number representing the number of files successfully movedfailed is a LIST of the filenames which could not be moved"""if( len(failed) > 0 and moved > 0 ):print '================================================================================'if( len(failed) > 0 and moved == 0 ):printwdheader(os.path.split(failed[0])[0])for f in failed:print "Failed to move %s" % fif( len(failed) == 0 and moved == 0 ):passelse:def printwdheader(dir):"""Prints out a header telling the user we're working in the directorypassed as an argument"""print 'Working in directory: %s' % dirprint '================================================================================'def printmove(num, file, dstdir):if( num == 1 ):printwdheader(os.path.split(file)[0])print "Moved %s to %s!" % (file, dstdir)def mainloop(dir, dict):"""mainloop(dir, dict):dir is of type STRINGdict is of type LIST of TUPLESRuns the main sort algorithm on the given directory using the pre-parseddictionary passed as a parameter."""files = getfiles(dir)subdirs = getdirs(dir)cwd=dirmoved = 0failed = []for regex, todir in dict:pattern = createpattern(regex)matches = getmatches(files, pattern)dstdir = get_dstdir(todir)for f in matches:ret = move_file(f, cwd, dstdir)if( ret == False ):failed.append(f)else:moved = moved + 1printmove(moved, f, dstdir)printfailed(moved, failed)# Call ourself recursively on the subdirectoriesfor s in subdirs:mainloop(s, dict)##### THE MAIN PROGRAM STARTS HERE #####if( __name__ == '__main__' ):print 'Regular Expression File Sorter (aka animesorter)'print '================================================================================'print 'Copyright (c) 2005, Ira W. Snyder (devel@irasnyder.com)'print 'All rights reserved.'print 'This program is licensed under the GNU GPL v2'dict = parsedict()mainloop(WORK_DIR, dict)print 'Goodbye!'