Subversion Repositories programming

Rev

Rev 180 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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