web-dev-qa-db-ja.com

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

ディレクトリとすべてのサブディレクトリの下にある特定のタイプ(*.pyなど)のすべてのファイルについて、md5チェックサムの要約を計算する必要があります。

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

編集:提案されたソリューションは非常に素晴らしいですが、これは正確に私が必要とするものではありません。すべてのサブディレクトリのコンテンツを含め、ディレクトリ全体を一意に識別するsingle summaryチェックサムを取得するソリューションを探しています。

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

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

テストディレクトリをコピーして、これをテストしました。

rsync -a ~/pybin/ ~/pybin2/

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

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

2bcf49a4d19ef9abd284311108d626f1  -
144
unutbu

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

tar c dir | md5sum

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

159
ire_and_curses

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

  • tarは、ディレクトリエントリをファイルシステムに格納されている順序で処理します。この順序を変更する方法はありません。異なる場所に「同じ」ディレクトリがある場合、これは事実上完全に異なる結果をもたらす可能性があり、これを修正する方法はわかりません(tarは入力ファイルを特定の順序で「ソート」できません)。
  • 私は通常、グループIDと所有者IDの番号が同じかどうかを気にしますが、グループ/所有者の文字列表現が同じかどうかは必ずしも気にしません。これは、たとえばrsync -a --deleteが行うことと一致しています。事実上すべて(xattrsとaclsを除く)を同期しますが、文字列表現ではなくIDに基づいて所有者とグループを同期します。したがって、必ずしも同じユーザー/グループを持たない別のシステムに同期した場合は、--numeric-ownerフラグをtarに追加する必要があります
  • 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つのディレクトリを区別しませんが、その可能性はほとんどありません。通常はfind-print0フラグでこれを修正しますが、ここでは他にもいろいろなことが行われているので、コマンドをもっと複雑にする価値のあるソリューションしか見ることができません。

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

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

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

44
Dieter_be

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

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

完全を期すために、 md5deep(1) ; * .pyフィルターの要件のために直接適用することはできませんが、find(1)と一緒にうまく機能するはずです。

10

私に最適なソリューション:

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
9
Tiago Lopo

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

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)
3
moander

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

cat *.py | md5sum 
3
Ramon

GNU find

find /path -type f -name "*.py" -exec md5sum "{}" +;
2
ghostdog74

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

2
jmucchiello

HashCopyを使用してこれを行います。単一のファイルまたはディレクトリでMD5およびSHAを生成および検証できます。 www.jdxsoftware.orgからダウンロードできます。

2
William Leng

md5deepを使用:

md5deep -r FOLDER | awk '{print $1}' | sort | md5sum

2

私は同じ問題を抱えていたので、ディレクトリ内のファイルの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
1
alan

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

cpio -i -e theDirname | md5sum
1
peterh

さらに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
Nick

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

0
MonkeyMonkey