#!/usr/bin/env python ''' Directory Monitoring Daemon class. Recognizes the following events: creation change [edit] move removal. ''' import os, sys, re, time, glob, fnmatch getmtime = os.path.getmtime getsize = os.path.getsize try: all except: def all(s): for x in s: if not x: return False return True try: set except: print >> sys.stderr, "Please update your version of python to 2.4 or later." sys.exit(1) class Monitor: ''' subclass this, and override removed, created, moved, and changed to do whatever you want. or, you can dynamically assign those methods to your functions. self.directories is a list of str's, and is passed either as the first argument to __init__, or as *args. self.mtimes maps filenames to mtimes [modification times]. ''' def __init__(self, *directories): if directories and (len(directories) == 1) and isinstance(directories[0], (tuple, list)): self.directories = list(directories[0]) else: self.directories = list(directories) self.mtimes = {} self.sizes = {} def removed(self, filename): print 'removed:', filename def created(self, filename): print 'created:', filename def moved(self, old_filename, new_filename): print 'moved:', old_filename, new_filename def changed(self, filename): print 'changed:', filename def stop(self): self.running = False def __call__(self): self.running = True for directory in self.directories: for dirpath, dirnames, filenames in os.walk(directory): for filename in filenames: filename = os.path.join(dirpath, filename) self.mtimes[filename] = getmtime(filename) self.sizes[filename] = getsize(filename) while self.running: previous_mtimes = dict(self.mtimes) previous_sizes = dict(self.sizes) changed = {} created = {} checked = {} for directory in self.directories: for dirpath, dirnames, filenames in os.walk(directory): for filename in filenames: filename = os.path.join(dirpath, filename) new_mtime = getmtime(filename) checked[filename] = new_mtime if filename not in self.mtimes: created[filename] = new_mtime self.mtimes[filename] = new_mtime self.sizes[filename] = getsize(filename) elif new_mtime > self.mtimes[filename]: self.changed(filename) changed[filename] = self.mtimes[filename] self.mtimes[filename] = new_mtime self.sizes[filename] = getsize(filename) removed = set(previous_mtimes.items()) - set(checked.items()) - set(changed.items()) if removed: if created: created_reversed = dict([(mtime, fn) for fn, mtime in created.iteritems()]) for old_fn, old_mtime in removed: if (old_mtime in created_reversed) and (self.sizes[created_reversed[old_mtime]] == previous_sizes[old_fn]): self.moved(old_fn, created_reversed[old_mtime]) del created[created_reversed[old_mtime]] else: self.removed(old_fn) del self.mtimes[old_fn] else: for fn, mtime in removed: self.removed(fn) del self.mtimes[fn] for fn in created: self.created(fn) def main(argv): ''' ''' Monitor(argv)() if __name__ == '__main__': sys.exit(main(sys.argv[1:]))