bash限定ですが。
何のこと?
似たファイル構造を持つ2つのディレクトリがあるときに、その中にあるファイルの差分を見たいってことがあると思います。
具体的にどんなときかと言うと、SVN/gitとかからレポジトリをCheckout/cloneしてきて、
そっちのディレクトリは触らずに、自分用にコピーを作って、それを編集して反映するのに差分を見る、とかです。
要は。
gitなりSVNなり使ってれば別にいいじゃん!ってことですが。
それを言っちゃうと今回のお話終わっちゃうので!
普通の方法。
まずはWindowsなら。
WinMergeさん最強です!
bashの時は。
比較する2つのディレクトリが dir1 と dir2 とします。
for file in `find dir1 -type f`
do
diff $file ${file/dir1/dir2}
done
とかやるとファイルだけ全比較してくれます。
ファイル名も出してみるのがこちら。
for file in `find dir1 -type f`
do
echo "-----" $file "-----"
diff $file ${file/dir1/dir2}
done
ただ、これだと差がないファイルもファイル名だけは出てしまって見づらいです。
なので、次の方法(私が良く使う方法)のご紹介!
for file in `find dir1 -type f`
do
diff -q $file ${file/dir1/dir2}
if [ $? -ne 0 ]; then
echo "-----" $file "-----"
diff $file ${file/dir1/dir2}
fi
done
2回diff取っちゃってますが、diffはファイルに違いがあると0以外を返すので、その終了コードを取って表示/非表示を切り替えてます。
実際に使う場合は最後にlessのパイプかませたりしてますけどね。
for file in `find dir1 -type f`
do
diff -q $file ${file/dir1/dir2}
if [ $? -ne 0 ]; then
echo -e "\n-----" $file "-----"
diff $file ${file/dir1/dir2}
fi
done | less
Tips
上で使ってる技術のいくつか説明。
find (ディレクトリ名) -type f
指定したディレクトリ以下のすべてのファイルだけを列挙します。
-type d
にするとディレクトリだけ。
なお、これシンボリックリンクはヒットしないので、
-type f -or -type l
とかにしないといけないんじゃないかと思います。
`(コマンド)`
コマンドを実行した結果を半角スペース区切りで一列に並べてくれます。
- でも良いこともあります。
たとえば、
$ ls
file1 file2
file3 file4
file5 file6
なときに、
$ echo `ls`
file1 file2 file3 file4 file5 file6
てな具合です。
同一のことをやってくれる別の表記としては $(...)
もあります。
`...`内で再度コマンドの結果を取りたいときにこの表記を使うとエスケープとか気にしないで良いので便利です。
$?
直前のコマンドの終了コードを取ります。
echo -e
改行とか入れたいときにはこのオプション付けるとOKです。
${変数名/置換前/置換後}
bashによる文字列置換です。
_変数名_で指定される変数が指す文字列に対し、_置換前_で指定される部分文字列を_置換後_に最初に見つけた1つだけ置き換えます。
もし全部置き換えたいときは ${変数名//置換前/置換後}
と_変数名_の後ろのスラッシュを2つ重ねます。
今回の目的は、2つのディレクトリを比較する、なので、最初のディレクトリ名だけ変わればOK!
むしろファイル名中にその文字列があるとそれも変わっちゃうとかは困るので、最初の置換だけにしてます。
diff -q
違いがあるかどうかだけ見ます。
ファイルが大きい時に便利。
diff $file ${file/dir1/dir2}
上に書いた通りではあるのですが、
- diffの第1引数 = $file = dir1の下のファイル名
- diffの第2引数 = ${file/dir1/dir2} = dir2の下のファイル名
となって、dir1とdir2の同じ階層にあるファイル同士を比較することになります。
最後に。
SVNとかgitとか使ってれば必要ない技術ですが、リリース版とテスト版をちょこちょこっと比較するには便利です!