指定日以降に変更されたファイルを抽出

指定日以降に変更されたファイルを抽出するPythonスクリプトです。

何らかのバージョン管理システムで管理している場合なら、ログをもとにパッチを作成できるけど、それができないときに使います。

日付表現が柔軟なので、しばらくして使い方忘れたとき、適当にやっても大丈夫なのが楽チンです。

$chsafter.py "2009/7/6 19:00" src dest
$chsafter.py 2009/7/6 src dest
$chsafter.py 7/6 src dest
$chsafter.py 19:00 src dest
chsafter.py:
#! /usr/bin/python
'''
usage:
    $ chsafter.py "2009/7/6 19:00" src dest
    
    Casual date formats are acceptable:
    $ chsafter.py 2009/7/6 src dest
    $ chsafter.py 7/6 src dest
    $ chsafter.py 19:00 src dest
'''

import sys, os, time, shutil
try:
    import dateutil.parser
except:
    print "prease install python-dateutil package via 'easy_install python-dateutil'."
    #wget http://peak.telecommunity.com/dist/ez_setup.py
    #./ez_setup.py
    #easy_install python-dateutil
    exit()

_DIR_EXCEPTS = ['.', '..', '.svn', '_svn']

def rec_filter_do(evaluter, executer, basedir, prefix=""):
    for entry in os.listdir(os.path.join(basedir, prefix)):
        abs_entry = os.path.join(basedir, prefix, entry)
        rel_entry = os.path.join(prefix, entry)
        if os.path.isdir(abs_entry) and entry not in _DIR_EXCEPTS:
            rec_filter_do(evaluter, executer, basedir, rel_entry)
        if os.path.isfile(abs_entry) and evaluter(rel_entry):
            executer(rel_entry)

def file_after(etime, filepath):
    return os.path.getmtime(filepath) >= etime

def file_before(etime, filepath):
    return os.path.getmtime(filepath) <= etime

def mirror_path(src, dest):
    if not os.path.exists(os.path.dirname(dest)):
        os.makedirs(os.path.dirname(dest))
    #print src
    shutil.copy2(src, dest)

def export_changes_after(timestr, srcdir, destdir):
    if os.path.exists(destdir):
        shutil.rmtree(destdir)
    os.makedirs(destdir)
    
    basetime = time.mktime(dateutil.parser.parse(timestr).timetuple())
    
    rec_filter_do(
        lambda p: file_after(basetime, os.path.join(srcdir, p)), #lambda p: file_before(...),
        lambda p: mirror_path(os.path.join(srcdir, p), os.path.join(destdir, p)),
        srcdir)

if __name__ == "__main__":
    
    if len(sys.argv) != 4:
        print "usage: chsafter.py <date, time or both> <src path> <dest path>"
        exit()
    
    destdir = sys.argv[3]
    if os.path.exists(destdir):
        r = ""
        while not (r.startswith('y') or r.startswith('n')):
            r = raw_input("%s is already exixts. clean all? (y/n)" % destdir).lower()
        if r.startswith('n'):
            exit()
        
    export_changes_after(*(sys.argv[1:]))

実行には python-dateutil パッケージが必要なので入れておきましょう。これ、日付文字列をdatetime型に変換するのがとにかく便利、損はしません。

以下の対象外ファイルは、場合に応じて書き換えてください。

_DIR_EXCEPTS = ['.', '..', '.svn', '_svn']