Subversion Repositories programming

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
116 ira 1
#!/usr/bin/python
2
 
121 ira 3
import os, re, shutil, sys
4
from optparse import OptionParser
116 ira 5
 
121 ira 6
### DEFAULT CONFIGURATION VARIABLES ###
175 ira 7
DICT_FILE = os.path.expanduser('~/.config/animesorter/animesorter.dict')
121 ira 8
WORK_DIR =  os.path.expanduser('~/downloads/usenet')
9
SORT_DIR =  os.path.expanduser('/data/Anime')
116 ira 10
 
121 ira 11
### Globals
12
options = {}
13
move_status = []
14
 
15
 
16
def parse_dict():
116 ira 17
    """Parses a dictionary file containing the sort definitions in the form:
18
    DIRECTORY = PATTERN
19
 
121 ira 20
    Returns a list of tuples of the form (compiled_regex, to_directory)"""
116 ira 21
    try:
121 ira 22
        f = open(options.dict_file, 'r', 0)
116 ira 23
        try:
24
            data = f.read()
25
        finally:
26
            f.close()
27
    except IOError:
121 ira 28
        print 'Error opening %s ... exiting!' % options.dict_file
116 ira 29
        sys.exit()
30
 
31
    ### Get a LIST containing each line in the file
32
    lines = [l for l in data.split('\n') if len(l) > 0]
33
 
34
    ### Split each line into a tuple, and strip each element of spaces
121 ira 35
    result = [(r, d) for r, d in [l.split('=') for l in lines]]
36
    result = [(r.strip() ,d.strip()) for r, d in result]
37
    result = [(re.compile(r), d) for r, d in result]
116 ira 38
 
121 ira 39
    return tuple(result)
116 ira 40
 
121 ira 41
def get_types_re():
42
    """Returns a compiled regular expression which will find objects of the
43
    types specified in this function's definition."""
129 ira 44
    types = ('avi', 'ogm', 'mkv', 'mp4')
121 ira 45
    types_regex = ''
116 ira 46
 
121 ira 47
    for i in types:
48
        types_regex += '%s|' % i
116 ira 49
 
121 ira 50
    types_regex = '.*(%s)$' % types_regex[:-1]
116 ira 51
 
121 ira 52
    return re.compile(types_regex, re.IGNORECASE)
116 ira 53
 
121 ira 54
def get_matches(files, pattern):
55
    """get_matches(files, pattern):
116 ira 56
 
57
    files is type LIST
58
    pattern is type sre.SRE_Pattern
59
 
60
    Returns a list of the files matching the pattern as type sre.SRE_Match."""
61
    matches = [m for m in files if pattern.search(m)]
62
    return matches
63
 
121 ira 64
def move_files(files, fromdir, todir):
65
    """move_files(files, fromdir, todir):
66
    Move the files represented by the list FILES from FROMDIR to TODIR"""
67
    ## Check for a non-default directory
68
    if todir[0] != '/':
69
        todir = os.path.join(options.output_dir, todir)
116 ira 70
 
121 ira 71
    ## Create the directory if it doesn't exist
72
    if not os.path.isdir(todir):
73
        try:
74
            os.makedirs(todir)
75
        except:
76
            move_status.append('FAILED to create directory: %s' % todir)
116 ira 77
 
121 ira 78
    ## Try to move every file, one at a time
79
    for f in files:
80
        srcname = os.path.join(fromdir, f)
81
        dstname = os.path.join(todir, f)
116 ira 82
 
121 ira 83
        try:
84
            shutil.move(srcname, dstname)
85
        except:
86
            move_status.append('FAILED to move %s to %s' % (f, todir))
87
            return
116 ira 88
 
121 ira 89
        move_status.append('Moved %s to %s' % (f, todir))
116 ira 90
 
121 ira 91
def print_prog_header():
92
    if options.verbose:
93
        print 'Regular Expression File Sorter (aka animesorter)'
94
        print '================================================================================'
95
        print 'Copyright (c) 2005, Ira W. Snyder (devel@irasnyder.com)'
96
        print 'All rights reserved.'
97
        print 'This program is licensed under the GNU GPL v2'
98
        print
116 ira 99
 
121 ira 100
def print_dir_header(dir):
101
    if options.verbose:
102
        print 'Working in directory: %s' % dir
116 ira 103
        print '================================================================================'
104
 
121 ira 105
def print_move_status():
106
    if options.verbose:
107
        for i in move_status:
108
            print i
116 ira 109
 
110
        print
111
 
121 ira 112
def get_parsed_options():
113
    parser = OptionParser()
114
    parser.add_option('-q', '--quiet', action='store_false', dest='verbose',
115
                      default=True, help='don\'t print status messages to stdout')
116
    parser.add_option('-d', '--dict', dest='dict_file', default=DICT_FILE,
117
                      help='read dictionary from FILE', metavar='FILE')
118
    #parser.add_option('-n', '--not-recursive', action='store_false', dest='recursive',
119
    #                   default=True, help='don\'t run recursively')
120
    parser.add_option('-s', '--start-dir', dest='start_dir', default=WORK_DIR,
121
                      help='start running at directory DIR', metavar='DIR')
122
    parser.add_option('-o', '--output-dir', dest='output_dir', default=SORT_DIR,
123
                      help='sort files into DIR', metavar='DIR')
116 ira 124
 
121 ira 125
    ## Parse the options
126
    (options, args) = parser.parse_args()
116 ira 127
 
121 ira 128
    ## Correct directories
129
    options.dict_file = os.path.abspath(options.dict_file)
130
    options.start_dir = os.path.abspath(options.start_dir)
131
    options.output_dir = os.path.abspath(options.output_dir)
116 ira 132
 
121 ira 133
    return options
116 ira 134
 
175 ira 135
def main():
116 ira 136
 
121 ira 137
    ## Get Options
138
    options = get_parsed_options()
116 ira 139
 
121 ira 140
    ## Print the program's header
141
    print_prog_header()
116 ira 142
 
121 ira 143
    ## Parse the dictionary
144
    dict = parse_dict()
116 ira 145
 
121 ira 146
    ## Start walking through directories
147
    for root, dirs, files in os.walk(options.start_dir):
116 ira 148
 
121 ira 149
        ## Blank the status variable
150
        move_status = []
116 ira 151
 
121 ira 152
        ## Get all of the files in the directory that are of the correct types
153
        types_re = get_types_re()
154
        raw_matches = [f for f in files if types_re.match(f)]
116 ira 155
 
121 ira 156
        ### Loop through the dictionary and try to move everything that matches
157
        for regex, todir in dict:
158
            matches = get_matches(raw_matches, regex)
116 ira 159
 
121 ira 160
            ## Move the files if we've found some
161
            if len(matches) > 0:
162
                move_files(matches, root, todir)
116 ira 163
 
121 ira 164
        if len(move_status) > 0:
165
            ## print header
166
            print_dir_header(root)
167
 
168
            ## print status
169
            print_move_status()
175 ira 170
 
171
### MAIN IS HERE ###
172
if __name__ == '__main__':
173
    main()
174