2 つのディレクトリツリーの差異を調べる Ruby クラス「DirDiff」
2 つのディレクトリの違い(片方にしかないファイルや変更されたファイル)を知りたいとか、それらの内容を同期させたいとかいうことって、よくありませんでしょうか。私もそういうことが何度かあって、そのたびに手抜きなスクリプトを組んでごまかしてきたのですが、いい加減あほらしくなってきたので、それなりに汎用性のあるものを作ってみました。
というわけで、本日ご紹介するのは、 2 つのディレクトリの違いをスキャンする Ruby クラス「DirDiff」です。相違のあるディレクトリ・ファイルごとにブロックを呼び出すので、目的に応じたさまざまな処理ができます。ぜひ使ってみてください!
ソースコード
まずはソースコードです。codeなにがしに投稿してあります。
ライブラリファイルは以下からダウンロードできます。
http://webos-goodies.googlecode.com/svn/trunk/products/rubylib/dirdiff/dirdiff.rb
基本的な使い方
例えば、 "~/old_dir" と "~/new_dir" を比べたいときは、以下のように呼び出します。
diff = DirDiff.new('~/old_dir', '~/new_dir') diff.each do |fname, type, operation| printf("%-16s %-10s %s\n", fname.inspect, type.inspect, operation.inspect) end
実行結果は以下のような感じになります。
"lost_dir" :directory :deleted "modified_file" :file :modified "added_file" :file :added
このように、追加・削除・変更があったファイルやディレクトリを簡単に取得できます。ここでは結果を表示しているだけですが、もちろん each メソッドのブロック内で任意の処理が実行できます。
リファレンス
上記の使い方でほとんどすべてなのですが、念のため DirDiff クラスの全パブリックメソッドの説明を掲載しておきます。
オブジェクトの作成
オブジェクトの作成は通例どおりクラスメソッド new で行います。
DirDiff.new(パス1, パス2, オプション)
引数はすべて省略可能です。オプションの詳細は後述。パス1, パス2を指定すると、すぐにツリーの比較を実行します。省略した場合は scan メソッドを使ってください。
scan メソッド
2 つのディレクトリツリーの比較を実行します。
diff.scan(パス1, パス2, オプション)
引数の意味は new と同じです。
each メソッド
追加・変更・削除のあったそれぞれのファイルに対してブロックを呼び出します。 new でパスを指定するか、 scan メソッドを呼び出した後でないと機能しません。
diff.each do |パス名, ファイルタイプ, 操作| ~ end
ブロックの引数のうち、パス名は追加・変更・削除のあったファイルのパス名で、 scan メソッドなどに与えたパスからの相対になっています。ファイルタイプは File.ftype の返り値と同じです。操作は以下のいずれかのシンボルです。
シンボル | 意味 |
---|---|
:added | パス2にのみ存在する |
:deleted | パス1にのみ存在する |
:modified | 両方に存在するが、内容が変更されている |
:modified はファイルの内容を比較して変更があった場合に適用されます。日付などは関係ありません。従って、ディレクトリが :modified になることはあり得ません。
empty? メソッド
ディレクトリの比較を行った後、変更があった場合は false 、なかった場合は true を返します。つまり、 each メソッドを実行してブロックが 1 回でも呼び出されるなら false になります。
scan メソッドのオプション
scan メソッドや new メソッドの第 3 引数には、以下のメンバを含むハッシュが指定できます。
- :shallow
- デフォルトでは、ディレクトリが追加・削除されると、それ以下の全ファイルが追加・削除されたものとしてエントリーされます。 :shallow オプションに true を指定すると、追加・削除された最上位のディレクトリのみがエントリーされます。
- :ignore
- 正規表現、もしくは正規表現の配列を指定します。ファイル名がそれらにマッチするファイルは結果から除外されます。マッチは、 each メソッドのブロックに渡されるファイル名と同じ文字列に対して行われます。
既知の問題
いつもどおり急ごしらえなので、いくつか問題点があります。
- ファイル名の大文字・小文字は常に区別されます。
- シンボリックリンクを正しく扱えません。
- 調べてみたら、まったく同じ名前でほぼ同機能のライブラリがありました。人間、考えることは同じですね。ま、あちらはちょっと使い方が面倒そうなので、よしとしよう(^^;
ほかにもお気づきの点がありましたら、お知らせください。
ご質問・ご要望・バグ報告などは Google グループへ
このクラスに関するご質問・ご要望・バグ報告には、以下の Google グループをご利用ください。 Google アカウントがあれば Web 上から投稿できますし、アカウントがなくてもメールで投稿できますので、お気軽にどうぞ。
以上、本日は 2 つのディレクトリツリーの相違を簡単に調査できる Ruby クラス「DirDiff」をご紹介しました。とくに利用制限などはありませんので、商用・非商用を問わず自由にお使いください。ご意見・ご要望などもお待ちしています!
詳しくはこちらの記事をどうぞ!
この記事にコメントする