読者です 読者をやめる 読者になる 読者になる

clock-up-blog

go-mi-tech

md5sum でディレクトリ単位のチェックサム計算等

Linux MinGW

異なる環境間でディレクトリ内容が一致していることを確認したい

md5sum をディレクトリ単位でかけるようなことをしたい。Linux または MinGW 環境にて。

要点ピックアップ(取り急ぎの人向け)

名前のみ確認。

$ cd 確認したいディレクトリ
$ find . | env LC_ALL=C sort | md5sum -b
81ac0d06a9d83180ecbf134261c9c056 *-    (※出力例)

内容含めて確認。

$ cd 確認したいディレクトリ
$ (find . -type f -exec md5sum -b {} \; && find .) | env LC_ALL=C sort | md5sum -b
c5d0e6b4ac616362456918163af4a215 *-    (※出力例)

前準備

とりあえず判定したいディレクトリに cd しておくこととする。問題を単純化するためにはこれが一番。

$ cd 確認したいディレクトリ

全ファイルの「名前」のチェックサム

全ファイルの全内容についてチェックサム計算しても良いけど、それだと時間かかりすぎるので、初弾としてはファイル名一覧のチェックサムを計算してみるのが良かろう。(ファイルの中身ではなく名前のみについてチェックサムを計算する)

$ find . | env LC_ALL=C sort | md5sum -b
e68cd72a60d88261a2e7f5710e1e38a7 *-

find によりファイル名一覧を出力し、一覧そのもののチェックサムを md5sum で計算する。環境により一覧の順序に差異が出ないようにソートを挟む必要がある。

ファイル数の確認

全ファイル名一覧のチェックサムがそもそも一致しなかった場合にはファイル数に過不足がある(またはファイル名に差異がある)のであろう。以下コマンドによりファイル数をチェックしてみると良い。

$ find . | wc -l
7

全ファイルの「内容」のチェックサム

全ファイルの内容をすべて結合した大きいファイルまたはストリームを作り、それのチェックサムを計算しても良い、、が、それは効率が悪い。実際にはファイル毎のチェックサムを個別に計算し、できあがったチェックサム一覧自体をさらにチェックサムすれば、事が足りる。

$ (find . -type f -exec md5sum -b {} \; && find .) | env LC_ALL=C sort | md5sum -b
c5d0e6b4ac616362456918163af4a215 *-

以上、ディレクトリ単位を比較するためのチェックサム計算。

解説

以下は興味ある人だけ読めば良いです。

全ファイルの個別チェックサム

$ find . -type f -exec md5sum -b {} \;

まず、これで全ファイルのチェックサムを計算する。一例として、結果は以下のようになる。

7e316cd82780aedf0d09bd41165b529d *./bbb/b.txt
e5828c564f71fea3a12dde8bd5d27063 *./bbb/b2.txt
591785b794601e212b260e25925636fd *./aaa/a.txt

個別チェックサム結果の順序を揃える

上記個別チェックサム結果の順序は find に依存していて、その find の吐き出すファイル一覧の順序は不定。なので、sort でまず順序を揃える。揃えないとその後のチェックサムの意味がなくなる。

$ find . -type f -exec md5sum -b {} \; | env LC_ALL=C sort
591785b794601e212b260e25925636fd *./aaa/a.txt
7e316cd82780aedf0d09bd41165b529d *./bbb/b.txt
e5828c564f71fea3a12dde8bd5d27063 *./bbb/b2.txt

頭にチェックサム値が来てるので、ファイル名順というよりはチェックサム値順になるのだが、用途としてはこれで足りる。

順序の揃った個別チェックサム結果について、さらにチェックサム計算する

$ find . -type f -exec md5sum -b {} \; | env LC_ALL=C sort | md5sum -b
1af83746233f2a227e5dfe942761a1d5 *-

これでほぼ仕上がり。

空フォルダが含まれていることも考慮する

上記コマンドでは、空フォルダの存在が無視されている(find の -f オプションにより)ので、空フォルダの有無も含めてしっかり比較するために、「find .」によりフォルダを含めた一覧を足す。

$ (find . -type f -exec md5sum -b {} \; && find .) | env LC_ALL=C sort | md5sum -b
c5d0e6b4ac616362456918163af4a215 *-

以上、ここまでが今回紹介したコマンドの構築の流れです。

オプション等解説

env LC_ALL=C の意味

環境の言語設定により、sort の順序は影響を受ける。
sort の順序が違うと一覧のチェックサムをかける意味がなくなってしまうため、順序を合わせるために LC_ALL を C として sort を実行する。

md5sum のオプションに「-b」を付けている理由

「-b」はファイルをバイナリモードとして扱うかどうかのオプション。Windows 環境でのみ意味のあるもの。

Windows 環境だとデフォルトで -b が付いた扱いになる。結果として出力にアスタリスクが付く。Linux では -b を付けても付けなくても比較方法は変わらないのだが、-b を付けないと出力にアスタリスクが付かない。

アスタリスクの有無が食い違うと、チェックサム一覧のチェックサムを計算する段階に支障が出る。そのため、アスタリスクを付けるためだけに「-b」を付与している。

応用

find の printf オプションによりパーミッション等を出力すればディレクトリ内容がパーミッションレベルで一致していることを確認したりもできる。

});