ディレクトリのmd5チェックサムを計算するにはどうすればよいですか?


133

*.pyディレクトリとすべてのサブディレクトリの下に配置された特定のタイプ(たとえば)のすべてのファイルの要約md5チェックサムを計算する必要があります。

それを行う最良の方法は何ですか?

編集:提案されたソリューションは非常に優れていますが、これは私が必要としているものとは正確には異なります。私は、ディレクトリ全体を一意に識別する単一の要約チェックサム(すべてのサブディレクトリのコンテンツを含む)を取得するソリューションを探しています。


見てください、この、この詳細な説明のために。
luvieere、2009年

3
スーパーユーザーの質問のようです。
ノルドリン2009年

8
チェックサムは何も一意に識別しないことに注意してください。
Hosam Aly

1
一意に識別したい「同じ」のディレクトリツリーが2つあるのはなぜですか。ファイルの作成/変更/アクセス時間は重要ですか?バージョン管理は本当に必要なものですか?
jmucchiello 2009年

私の場合、本当に重要なのは、ディレクトリツリー全体のコンテンツの類似性です。これは、次のことを意味します。1)ディレクトリツリーの下のファイルのコンテンツは変更されていない2)ディレクトリツリーに新しいファイルが追加されていない3)ファイルがない削除されました
victorz 2009年

回答:


152
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum

findコマンドは、.pyで終わるすべてのファイルをリストします。md5sumは.pyファイルごとに計算されます。awkはmd5sumsを選択するために使用されます(一意でない可能性があるファイル名は無視されます)。md5sumがソートされます。次に、このソートされたリストのmd5sumが返されます。

私はテストディレクトリをコピーしてこれをテストしました:

rsync -a ~/pybin/ ~/pybin2/

〜/ pybin2にあるいくつかのファイルの名前を変更しました。

このfind...md5sumコマンドは、両方のディレクトリに対して同じ出力を返します。

2bcf49a4d19ef9abd284311108d626f1  -

24
ファイルの名前が変更されると、同じチェックサムが生成されることに注意してください。したがって、署名のファイルレイアウトの部分を考慮する場合、これは「ディレクトリ全体を一意に識別するチェックサム」には適合しません。
Valentin Milea、2012年

1
コマンドラインをわずかに変更して、各ファイルのチェックサムの前にファイルの名前(さらには/ path / to / dir /からのファイルの相対パス)を付けると、最終的なチェックサムで考慮されます。
Michael Zilbermann、2013年

4
@ zim2001:はい、それは変更することができるが、私は、問題(質問の下のOPのコメントに特に起因する)を理解できるように、OPがあれば任意の二つのディレクトリが等しいと考えることがしたかったコンテンツファイルのファイル名に関係なく同一でしたか相対パスも。
unutbu 2013年

@unutbu:わかっています。バレンティンミレアからの前のメモに反応していました。
Michael Zilbermann 2013年

awk ...シグネチャのレイアウト部分を検討する場合は、@ ValentinMileaがその部分を削除するだけです。
segfault 2013

166

その場でtarアーカイブファイルを作成し、それをmd5sum次の場所にパイプします。

tar c dir | md5sum

これにより、ファイルとサブディレクトリのセットアップに固有の単一のmd5sumが生成されます。ディスク上にファイルは作成されません。


25
@CharlesBに単一のチェックサムを使用すると、どのファイルが異なるかがわかりません。問題は、ディレクトリの単一のチェックサムに関するものでした。
ホーケン、2012

17
ls -alR dir | md5sum。これは、読み取りだけで圧縮しないほうがよいです。コンテンツはMODの時間とファイルのサイズが含まれているので、それはユニークです;)
シド

14
@ Daps0l-コマンドに圧縮はありません。zgzipまたはjbzip2 を追加する必要があります。どちらもしていません。
ire_and_curses

7
これを行うと、ファイルのコンテンツだけでなく、ファイルのタイムスタンプやその他のものがチェックサム計算に統合されることに注意してください
Michael Zilbermann

10
これはかわいいですが、実際には機能しません。tar同じファイルのセットを2回、または2台の異なるコンピューターで実行しても、まったく同じ結果が得られる保証はありません。
2014

46

ire_and_cursesの使用tar c <dir>に関する提案には、いくつかの問題があります。

  • tarは、ファイルシステムに格納されている順序でディレクトリエントリを処理します。この順序を変更する方法はありません。別の場所に「同じ」ディレクトリがある場合、これは事実上完全に異なる結果をもたらす可能性があり、私はこれを修正する方法を知りません(tarは入力ファイルを特定の順序で「ソート」できません)。
  • 私は通常、groupidとowneridの番号が同じであるかどうかを気にします。必ずしもgroup / ownerの文字列表現が同じであるかどうかは関係ありません。これは、たとえば何をしているのかと一致してrsync -a --deleteいます。事実上すべて(xattrsとaclsを除く)を同期しますが、所有者とグループは文字列表現ではなくIDに基づいて同期します。したがって、必ずしも同じユーザー/グループを持たない別のシステムに同期した場合は、--numeric-ownertarにフラグを追加する必要があります
  • tarには、確認するディレクトリのファイル名が含まれます。

最初の問題が修正されていない限り(または、影響がないことが確実でない限り)、このアプローチは使用しません。

find彼らは唯一のあなたがチェックサムは、心の中で空のディレクトリを維持する必要がある場合は問題になるファイルは、いないディレクトリが含まれるため、上記の提案に基づく解決策もダメではありません。

最後に、照合はシステム間で異なる可能性があるため、ほとんどの提案されたソリューションは一貫してソートされません。

これは私が思いついた解決策です:

dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum

このソリューションに関するメモ:

  • LC_ALL=Cシステム間で信頼性のソート順序を確保することです
  • これは、「named \ nwithanewline」というディレクトリと「named」と「withanewline」という2つのディレクトリを区別しませんが、その可能性は非常に低いようです。通常はこれを-print0フラグで修正findしますが、ここでは他のことが行われているため、コマンドをより複雑にし、価値がある解決策しか見ることができません。

PS:私のシステムの1つは、フラグもfindサポートしていない限られたbusybox を使用しています。また、ディレクトリを示すために「/」を追加していますが、findutils findはそうではないため、このマシンでは実行する必要があります。-exec-print0

dir=<mydir>; (find "$dir" -type f | while read f; do md5sum "$f"; done; find "$dir" -type d | sed 's#/$##') | LC_ALL=C sort | md5sum

幸い、名前に改行が含まれるファイルやディレクトリはありません。そのため、このシステムでは問題になりません。


1
+1:非常に興味深い!ファイルシステムの種類によって、または同じファイルシステム内で順序が異なる可能性があるとおっしゃっていますか?
ire_and_curses 2011年

2
両方とも。各ディレクトリ内のディレクトリエントリの順序に依存します。AFAIKディレクトリエントリ(ファイルシステム内)は、「ディレクトリにファイルを作成する」順序で作成されます。簡単な例:$ mkdir a; / file-1をタッチします。touch a / file-2 $ mkdir b; b / file-2にタッチします。タッチB /ファイル1 $(CD;タール-c | md5sumは。)fb29e7af140aeea5a2647974f7cdec77 - $(CD bの;タール-c | md5sumは)a3a39358158a87059b9f111ccffa1023 -
Dieter_be

15

空のディレクトリではなくファイルのみに関心がある場合、これはうまく機能します。

find /path -type f | sort -u | xargs cat | md5sum


9

私にとって最も効果的な解決策:

find "$path" -type f -print0 | sort -z | xargs -r0 md5sum | md5sum

それが私にとって最もうまくいった理由:

  1. スペースを含むファイル名を処理します
  2. ファイルシステムのメタデータを無視します
  3. ファイルの名前が変更されたかどうかを検出します

他の回答に関する問題:

ファイルシステムのメタデータは無視されません:

tar c - "$path" | md5sum

スペースを含むファイル名を処理せず、ファイルの名前が変更されたかどうかも検出しません。

find /path -type f | sort -u | xargs cat | md5sum

4

ディレクトリ全体にわたる1つのmd5sumが必要な場合は、次のようにします

cat *.py | md5sum 

1
サブディレクトリにはcat **.py|のようなものを使用します。md5sum
Ramon、

3

コンテンツとファイル名の両方を含むすべてのファイルのチェックサム

grep -ar -e . /your/dir | md5sum | cut -c-32

上記と同じですが、*。pyファイルのみが含まれます

grep -ar -e . --include="*.py" /your/dir | md5sum | cut -c-32

必要に応じて、シンボリックリンクをたどることもできます

grep -aR -e . /your/dir | md5sum | cut -c-32

grepでの使用を検討できるその他のオプション

-s, --no-messages         suppress error messages
-D, --devices=ACTION      how to handle devices, FIFOs and sockets;
-Z, --null                print 0 byte after FILE name
-U, --binary              do not strip CR characters at EOL (MSDOS/Windows)


2

技術的には、を実行するだけで済みますls -lR *.py | md5sum。誰かがファイルを変更して元の日付に戻し、ファイルのサイズを変更しないことを心配しない限り、からの出力lsはファイルが変更されたかどうかを通知します。私のunix-fooは弱いので、印刷するための作成時間と変更時間を取得するには、さらにいくつかのコマンドラインパラメータが必要になる場合があります。lsファイルのアクセス許可が変更されているかどうかも通知されます(気にしない場合は、それをオフにするスイッチがあるはずです)。


3
これは一部のユースケースに適合する場合がありますが、一般的には、チェックサムに日付のみではなく内容のみを反映させる必要があります。たとえばtouch、ファイルの日付を変更する(内容変更しない)場合、チェックサムは変更されないことが期待されます。
トッドオーウェン、


1

私は同じ問題を抱えていたので、ディレクトリ内のファイルのmd5sumを一覧表示するだけのこのスクリプトを思いつきました。サブディレクトリがそこから再度実行されると、スクリプトが現在のスクリプトを実行できるようになる必要があります。上記の引数が$ 1で渡される場合、ディレクトリまたはサブディレクトリから

#!/bin/bash

if [ -z "$1" ] ; then

# loop in current dir
ls | while read line; do
  ecriv=`pwd`"/"$line
if [ -f $ecriv ] ; then
    md5sum "$ecriv"
elif [ -d $ecriv ] ; then
    sh myScript "$line" # call this script again
fi

done


else # if a directory is specified in argument $1

ls "$1" | while read line; do
  ecriv=`pwd`"/$1/"$line

if [ -f $ecriv ] ; then
    md5sum "$ecriv"

elif [ -d $ecriv ] ; then
    sh myScript "$line"
fi

done


fi

ファイル名にスペースまたは引用符が含まれている場合、このスクリプトが失敗することはほぼ間違いありません。私はこれがbashスクリプトで面倒だと思いますが、私がすることはIFSを変更することです。
localhost

1

ファイルシステムの属性や一部のtarバージョンのビットレベルの違いからの独立性が本当に必要な場合は、cpioを使用できます。

cpio -i -e theDirname | md5sum

0

さらに2つの解決策があります。

作成:

du -csxb /path | md5sum > file

ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum > /tmp/file

小切手:

du -csxb /path | md5sum -c file

ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum -c /tmp/file

0

md5sumは問題なく動作しましたが、sortファイル名の並べ替えや問題がありました。代わりに、md5sum結果でソートしました。また、同等の結果を作成するために、いくつかのファイルを除外する必要がありました。

find . -type f -print0 \ | xargs -r0 md5sum \ | grep -v ".env" \ | grep -v "vendor/autoload.php" \ | grep -v "vendor/composer/" \ | sort -d \ | md5sum

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.