LoginSignup
9

More than 5 years have passed since last update.

posted at

updated at

2つのディレクトリ内の差分を見る。

bash限定ですが。

何のこと?

似たファイル構造を持つ2つのディレクトリがあるときに、その中にあるファイルの差分を見たいってことがあると思います。

具体的にどんなときかと言うと、SVN/gitとかからレポジトリをCheckout/cloneしてきて、
そっちのディレクトリは触らずに、自分用にコピーを作って、それを編集して反映するのに差分を見る、とかです。

要は。

gitなりSVNなり使ってれば別にいいじゃん!ってことですが。
それを言っちゃうと今回のお話終わっちゃうので!

普通の方法。

まずはWindowsなら。

WinMergeさん最強です!

bashの時は。

比較する2つのディレクトリが dir1 と dir2 とします。

directory_diff_1.sh
for file in `find dir1 -type f`
do
    diff $file ${file/dir1/dir2}
done

とかやるとファイルだけ全比較してくれます。
ファイル名も出してみるのがこちら。

directory_diff_2.sh
for file in `find dir1 -type f`
do
    echo "-----" $file "-----"
    diff $file ${file/dir1/dir2}
done

ただ、これだと差がないファイルもファイル名だけは出てしまって見づらいです。
なので、次の方法(私が良く使う方法)のご紹介!

directory_diff_3.sh
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のパイプかませたりしてますけどね。

directory_diff_4.sh
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とか使ってれば必要ない技術ですが、リリース版とテスト版をちょこちょこっと比較するには便利です!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
9