« [python/備忘録] ホームディレクトリに Python をインストール | トップページ | [ C ] C 言語で FizzBuzz -- やっぱり邪悪編? -- »

2007/06/19

[python] Workshop Edge2007 お題1 -- Synchronizing Directory

二つのディレクトリ(フォルダ)を指定すると、そのディレクトリの下の全てのファイルについて「片方にしかないファイルはもう片方へコピーし、両方にあるけどもタイムスタンプ(更新時刻)の異なるファイルは新しい方で古い方を上書きする」という処理を行うプログラムを作りなさい。

個人的な目標

  • 集合演算を使う
  • 20行以内にする
import os, shutil, stat

get_timestamp = lambda filename: os.stat( filename )[stat.ST_MTIME]
get_filelist  = lambda dir_path: [os.path.join( node[0], filename ) for node in os.walk( dir_path ) for filename in node[2]]
get_dir_info  = lambda dir_path: dict( zip( get_filelist( dir_path ), [get_timestamp( filename ) for filename in get_filelist( dir_path )] ) )

def synchronize_directories( dir1, dir2 ):
    (dir1_info, dir2_info) = map( get_dir_info, (dir1, dir2) )
    (symmetric_difference, intersection) = map( lambda method: eval( "set.%s( set([filename[len( dir1 ):] for filename in dir1_info.keys()]), set([filename[len( dir2 ):] for filename in dir2_info.keys()]) )" % method ), ["symmetric_difference", "intersection"] )

    # copies lacked files
    # It is necessary to make intermediate path before copying or replacing file.
    # For example, imagine dir_path=X:\hoge and filename=X:\hoge\piyo\fuge\bar.txt. In this case, intermediate path is /piyo/hoge.
    # At first, using expression "os.path.split( orz )[0][len( dir_path ):]" to get the path and then make path by 
    # os.makedirs( os.path.abspath( target_directory ) + intermediate_path )
    if symmetric_difference:
        for filename in symmetric_difference:
            (source_directory, distination_directory) = ((dir1 if True in [(filename in element) for element in dir1_info] else dir2), 
                                                         (dir1 if not(True in [(filename in element) for element in dir1_info]) else dir2))
            intermediate_path = os.path.split( source_directory )[0][len( dir1 ):]
            os.makedirs( os.path.abspath( destination_directory ) + intermediate_path )
            shutil.copy( os.path.join( source_directory, filename ), os.path.join( destination_directory, intermediate_path ) )

    # replace old files by later files
    if intersection:
        for filename in intersection:
            # by comparing timestamps, discriminate which is later, which is destination directory
            (later_file, destination_directory) = (os.path.join( dir1, filename ), os.path.join( dir2, os.path.split( filename )[0])) if dir1_info[os.path.join(dir1, filename)] > dir2_info[os.path.join( dir2, filename )] else (os.path.join( dir2, filename ), os.path.join( dir1, os.path.split( filename )[0]))
            
            os.makedirs( os.path.abspath( destination_directory + os.path.split( later_file )[0][len( dir1 ):] ) )
            shutils.copy( later_file, destination_directory )

目標達成ならず 31 行 _| ̄|○il|!
先週見た時は集合演算を使った回答がなかったので集合演算を取り入れてみました。

もしかしたらバグがあるかも。見つけたらご連絡くださいませ m(_ _)m

2007.06.19 23:58 追記
うまくトラックバックが遅れないようなので、コメントで投稿しました。
あちらだとコードが途中で切れていますが・・・

2007.06.20 15:00
ソースファイル添付忘れていたので添付しました。
こちら

2007.06.20 21:51
アップ直前に加えた変更が原因で SyntaxError が発生してしまうのを修正。
ご通知ありがとうございました。どんなに忙しくても最低でもデバッガに通すべきでした。
反省しております。

|

« [python/備忘録] ホームディレクトリに Python をインストール | トップページ | [ C ] C 言語で FizzBuzz -- やっぱり邪悪編? -- »

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/103108/15494439

この記事へのトラックバック一覧です: [python] Workshop Edge2007 お題1 -- Synchronizing Directory:

« [python/備忘録] ホームディレクトリに Python をインストール | トップページ | [ C ] C 言語で FizzBuzz -- やっぱり邪悪編? -- »