web-dev-qa-db-ja.com

md5ディレクトリツリー内のすべてのファイル

次のような構造のディレクトリがあります。

.
├── Test.txt
├── Test1
│   ├── Test1.txt
│   ├── Test1_copy.txt
│   └── Test1a
│       ├── Test1a.txt
│       └── Test1a_copy.txt
└── Test2
   ├── Test2.txt
   ├── Test2_copy.txt
   └── Test2a
       ├── Test2a.txt
       └── Test2a_copy.txt

このディレクトリ内のすべてのファイルのmd5チェックサムを作成するbashスクリプトを作成したいと思います。 CLIでスクリプト名を入力し、次にハッシュしたいディレクトリへのパスを入力して、機能させたいと思います。これを達成する方法はたくさんあると確信しています。現在私が持っているもの:

#!/bin/bash

for file in "$1" ; do 
    md5 >> "${1}__checksums.md5"
done

これはただハングし、機能しません。おそらくfindを使用する必要がありますか?

1つの注意点-ハッシュしたいディレクトリには異なる拡張子のファイルがあり、必ずしもこのまったく同じツリー構造を持つとは限りません。これらのさまざまな状況でも機能するものが必要です。

15
Bleakley

md5deepを使用

md5deep -r path/to/dir > sums.md5

findおよびmd5sumの使用

find relative/path/to/dir -type f -exec md5sum {} + > sums.md5

md5sum -c sums.md5を使用してMD5サムのチェックを実行する場合、sums.md5ファイルを生成したディレクトリと同じディレクトリから実行する必要があることに注意してください。これは、findが現在の場所に相対的なパスを出力し、sums.md5ファイルに配置されるためです。

これが問題になる場合は、relative/path/to/dirを絶対にすることができます(たとえば、$PWD/をパスの前に置くことで)。これにより、任意の場所からsums.md5でチェックを実行できます。欠点は、現在sums.md5に絶対パスが含まれているため、それが大きくなることです。

findおよびmd5sumを使用するフル機能の関数

この関数を.bashrcファイル($HOMEディレクトリにあります)に配置できます。

function md5sums {
  if [ "$#" -lt 1 ]; then
    echo -e "At least one parameter is expected\n" \
            "Usage: md5sums [OPTIONS] dir"
  else
    local OUTPUT="checksums.md5"
    local CHECK=false
    local MD5SUM_OPTIONS=""

    while [[ $# > 1 ]]; do
      local key="$1"
      case $key in
        -c|--check)
          CHECK=true
          ;;
        -o|--output)
          OUTPUT=$2
          shift
          ;;
        *)
          MD5SUM_OPTIONS="$MD5SUM_OPTIONS $1"
          ;;
      esac
      shift
    done
    local DIR=$1 

    if [ -d "$DIR" ]; then  # if $DIR directory exists
      cd $DIR  # change to $DIR directory
      if [ "$CHECK" = true ]; then  # if -c or --check option specified
        md5sum --check $MD5SUM_OPTIONS $OUTPUT  # check MD5 sums in $OUTPUT file
      else                          # else
        find . -type f ! -name "$OUTPUT" -exec md5sum $MD5SUM_OPTIONS {} + > $OUTPUT  # Calculate MD5 sums for files in current directory and subdirectories excluding $OUTPUT file and save result in $OUTPUT file
      fi
      cd - > /dev/null  # change to previous directory
    else
      cd $DIR  # if $DIR doesn't exists, change to it to generate localized error message
    fi
  fi
}

source ~/.bashrcを実行した後、通常のコマンドと同様にmd5sumsを使用できます。

md5sums path/to/dir

このディレクトリとサブディレクトリ内のすべてのファイルのMD5合計を含むchecksums.md5ディレクトリにpath/to/dirファイルを生成します。使用する:

md5sums -c path/to/dir

path/to/dir/checksums.md5ファイルから合計をチェックします。

path/to/dirは相対でも絶対でもかまいません。md5sumsはどちらの方法でも正常に動作します。結果のchecksums.md5ファイルには、常にpath/to/dirからの相対パスが含まれます。別のファイル名を使用し、checksums.md5または-oオプションを指定することにより、デフォルトの--outputを使用できます。 -c--check-o、および--output以外のすべてのオプションは、md5sumに渡されます。

md5sums関数定義の前半は、オプションの解析を担当します。詳細については this answer を参照してください。後半には説明コメントが含まれています。

27
TeWu

どうですか:

find /path/you/need -type f -exec md5sum {} \; > checksums.md5

pdate#1: @twalbergの推奨に基づいて、ファイル名の空白を処理するコマンドを改善しました。

pdate#2: @jilの提案に基づいて改善され、不要なxargs呼び出しを削除し、代わりにfindの-execオプションを使用します。

pdate#3: @Blakeスクリプトの単純な実装は次のようになります。

#!/bin/bash
# Usage: checksumchecker.sh <path>
find "$1" -type f -exec md5sum {} \; > "$1"__checksums.md5
4
taskalman
#!/bin/bash
shopt -s globstar
md5sum "$1"/** > "${1}__checksums.md5"

説明:shopt -s globstar(manual) は、**再帰グロブワイルドカードを有効にします。これは、"$1"/**がパラメーター$1として指定されたディレクトリの下で再帰的にすべてのファイルのリストに展開されることを意味します。次に、このファイルリストをパラメーターとしてmd5sumを呼び出すだけで、> "${1}__checksums.md5"が出力をファイルにリダイレクトします。

2
jil
md5deep -r $your_directory | awk {'print $1'} | sort | md5sum | awk {'print $1'}

更新された回答

以下の回答または他の回答が気に入った場合は、コマンドを実行する関数を作成できます。そのため、テストするには、ターミナルに次を入力して関数を宣言します。

function sumthem(){ find "$1" -type f -print0 | parallel -0 -X md5 > checksums.md5; }

次に、使用することができます:

sumthem /Users/somebody/somewhere

希望どおりに機能する場合は、その行を "bash profile"の最後に追加すると、関数はいつでも宣言され、使用可能になります。あなたの "bash profile"はおそらく$HOME/.profile

元の回答

すべてのCPUコアを並行して動作させてみませんか?

find . -type f -print0 | parallel -0 -X md5sum

これにより、すべてのファイル(-type f)現在のディレクトリ(.)最後にヌルバイトを付けて出力します。次に、これらはGNU Parallelに渡され、ファイル名がヌルバイト(-0)および一度にできるだけ多くのファイルを実行する必要があること(-X)ファイルごとに新しいプロセスを作成して保存し、ファイルをmd5sumする必要があります。

このアプローチは、Photoshopファイルのような大きな画像に対して、速度が遅いという点で最大のボーナスを支払います。

1
Mark Setchell