Rev 116 | Blame | Last modification | View Log | RSS feed
#!/usr/bin/python
import sys, os, glob, re, shutil
DICT_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 = PATTERN
Returns 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!' % dict
sys.exit()
### Get a LIST containing each line in the file
lines = [l for l in data.split('\n') if len(l) > 0]
### Split each line into a tuple, and strip each element of spaces
tuples = [(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 STRING
Return a LIST of the files of type *.{avi,ogm,mkv} that are in the
directory given as a parameter."""
files = []
types = ('avi', 'ogm', 'mkv')
# Match every type in the type array
for 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 files
def getdirs(dir=WORK_DIR):
"""getdirs(dir):
dir is type STRING
Return 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 dirs
def createpattern(string):
"""createpattern(string):
Returns a sre.SRE_Pattern created from the string given as a parameter."""
pattern = re.compile(string)
return pattern
def getmatches(files, pattern):
"""getmatches(files, pattern):
files is type LIST
pattern is type sre.SRE_Pattern
Returns a list of the files matching the pattern as type sre.SRE_Match."""
matches = [m for m in files if pattern.search(m)]
return matches
def fname_from_match(match):
"""fname_from_match(match):
match is a LIST containing type sre.SRE_Match
Returns a string (the filename) of the LIST match given as a parameter."""
fname = ''.join(match.string)
return fname
def getmatchnames(matches):
"""getmatchnames(matches):
matches is a String containing (many) objects of type sre.SRE_Match
Returns a LIST of STRINGS representing the filenames of the matches."""
matchnames = [fname_from_match(n) for n in matches]
return matchnames
def 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 currently
destdir is a STRING representing the directory to move the file to
Returns 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 False
return True
def get_dstdir(dir):
"""get_dstdir(dir):
Get an appropriate destination directory depending on whether dir
has a slash on the beginning"""
if( dir[0] == '/' ):
return dir
return os.path.join(SORT_DIR, dir)
def printfailed(moved, failed, cwd):
"""printfailed(moved, failed, cwd):
moved is an INTEGER number representing the number of files successfully moved
failed is a LIST of the filenames which could not be moved
cwd is a STRING containing the current working directory"""
if( len(failed) > 0 and moved > 0 ):
print '================================================================================'
if( len(failed) > 0 and moved == 0 ):
printwdheader(cwd)
for f in failed:
print "Failed to move %s" % f
if( len(failed) == 0 and moved == 0 ):
pass
else:
def printwdheader(dir):
"""Prints out a header telling the user we're working in the directory
passed as an argument"""
print 'Working in directory: %s' % dir
print '================================================================================'
def printmove(num, file, dstdir, cwd):
if( num == 1 ):
printwdheader(cwd)
print "Moved %s to %s!" % (file, dstdir)
def mainloop(dir, dict):
"""mainloop(dir, dict):
dir is of type STRING
dict is of type LIST of TUPLES
Runs the main sort algorithm on the given directory using the pre-parsed
dictionary passed as a parameter."""
files = getfiles(dir)
subdirs = getdirs(dir)
cwd=dir
moved = 0
failed = []
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 + 1
printmove(moved, f, dstdir, cwd)
printfailed(moved, failed, cwd)
# Call ourself recursively on the subdirectories
for 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!'