web-dev-qa-db-ja.com

Linux:指定されたフォルダーとコンテンツに対して単一のハッシュを計算しますか?

簡単にこれを行う方法があるはずです!

sha1summd5sumなどのLinuxコマンドラインアプリを試しましたが、個々のファイルのハッシュを計算し、各ファイルに1つずつハッシュ値のリストを出力できるようです。

(ファイル名だけでなく)フォルダのコンテンツ全体に対して単一のハッシュを生成する必要があります。

私は次のようなことをしたいです

sha1sum /folder/of/stuff > singlehashvalue

編集:明確にするために、私のファイルはディレクトリツリー内の複数のレベルにあり、それらはすべて同じルートフォルダにあるわけではありません。

72
Ben L

可能な方法の1つは次のとおりです。

 sha1sum path/to/folder/* | sha1sum 

ディレクトリツリー全体が存在する場合は、おそらくfindとxargsを使用することをお勧めします。可能なコマンドの1つは

 path/to/folder -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum 

そして最後に、パーミッションと空のディレクトリも考慮する必要がある場合:

(find path/to/folder -type f -print0  | sort -z | xargs -0 sha1sum;
 find path/to/folder \( -type f -o -type d \) -print0 | sort -z | \
   xargs -0 stat -c '%n %a') \
| sha1sum

statの引数により、ファイル名が出力され、その後に8進数の許可が出力されます。 2つの検索は次々に実行され、ディスクIOの量が2倍になります。最初はすべてのファイル名を検索して内容をチェックサムし、2番目はすべてのファイル名とディレクトリ名を検索し、名前とモードを印刷します。 「ファイル名とチェックサム」のリストと、それに続く「パーミッション付きの名前とディレクトリ」は、チェックサムを小さくするためにチェックサムされます。

92
Vatine
  • aide のようなファイルシステム侵入検知ツールを使用します。

  • ディレクトリのtarボールをハッシュします:

    tar cvf - /path/to/folder | sha1sum

  • vatine's oneliner :のように、自分で何かをコーディングします。

    find /path/to/folder -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum

21
David Schmitt

できるよ tar -c /path/to/folder | sha1sum

9
S.Lott

フォルダ内の何かが変更されたかどうかだけを確認したい場合は、これをお勧めします。

ls -alR --full-time /folder/of/stuff | sha1sum

フォルダ、サブフォルダ、それらのファイル、タイムスタンプ、サイズ、アクセス許可を含むls出力のハッシュを提供します。何かが変更されたかどうかを判断するために必要なほとんどすべてのもの。

このコマンドは各ファイルのハッシュを生成しないことに注意してください。ただし、findを使用するよりも高速である必要があります。

6
Shumoapp

ファイルの内容をハッシュし、ファイル名を無視したい場合は、使用できます

cat $FILES | md5sum

ハッシュを計算するときは、ファイルが同じ順序になっていることを確認してください。

cat $(echo $FILES | sort) | md5sum

ただし、ファイルのリストにディレクトリを含めることはできません。

3
unbeknown

堅牢でクリーンなアプローチ

  • まず最初に、利用可能なメモリを独占しないでください!ファイル全体をフィードするのではなく、ファイルをチャンクでハッシュします。
  • さまざまなニーズ/目的のためのさまざまなアプローチ(以下のすべてまたは適用するものを選択):
    • ディレクトリツリー内のすべてのエントリのエントリ名のみをハッシュする
    • すべてのエントリのファイルの内容をハッシュします(メタデータ、iノード番号、ctime、atime、mtime、サイズなどを残して、アイデアを得ます)
    • シンボリックリンクの場合、そのコンテンツは参照先名です。ハッシュするか、スキップすることを選択します
    • エントリのコンテンツをハッシュしながら、シンボリックリンクをフォローするかどうか(解決された名前)
    • ディレクトリの場合、その内容は単なるディレクトリエントリです。再帰的にトラバースする間、それらは最終的にハッシュされますが、そのレベルのディレクトリエントリ名をハッシュしてこのディレクトリにタグを付ける必要がありますか?内容をハッシュするために深くトラバースする必要なく、変更を迅速に識別するためにハッシュが必要なユースケースで役立ちます。例としては、ファイル名の変更がありますが、残りのコンテンツは同じままで、すべてかなり大きなファイルです
    • 大きなファイルを適切に処理する(もう一度、RAMに注意する)
    • 非常に深いディレクトリツリーを処理する(開いているファイル記述子に注意する)
    • 非標準のファイル名を処理する
    • ソケット、パイプ/ FIFO、ブロックデバイス、charデバイスであるファイルを処理する方法それらもハッシュする必要がありますか?
    • トラバース中にエントリのアクセス時間を更新しないでください。これは、特定のユースケースでは副作用であり、逆効果(直感的?)になるためです。

これは私が私の頭の上に持っているものであり、実際にこれに取り組んでいる人は誰でも他の落とし穴やコーナーケースを捕まえていたでしょう。

ここにツールがあります 、ほとんどの場合に対処する非常に軽いメモリは、エッジの周りが少し荒いかもしれませんが、非常に役立ちました。

dtreetrawlの使用例と出力。

Usage:
  dtreetrawl [OPTION...] "/trawl/me" [path2,...]

Help Options:
  -h, --help                Show help options

Application Options:
  -t, --terse               Produce a terse output; parsable.
  -j, --json                Output as JSON
  -d, --delim=:             Character or string delimiter/separator for terse output(default ':')
  -l, --max-level=N         Do not traverse tree beyond N level(s)
  --hash                    Enable hashing(default is MD5).
  -c, --checksum=md5        Valid hashing algorithms: md5, sha1, sha256, sha512.
  -R, --only-root-hash      Output only the root hash. Blank line if --hash is not set
  -N, --no-name-hash        Exclude path name while calculating the root checksum
  -F, --no-content-hash     Do not hash the contents of the file
  -s, --hash-symlink        Include symbolic links' referent name while calculating the root checksum
  -e, --hash-dirent         Include hash of directory entries while calculating root checksum

人間に優しい出力のスニペット:

...
... //clipped
...
/home/lab/linux-4.14-rc8/CREDITS
        Base name                    : CREDITS
        Level                        : 1
        Type                         : regular file
        Referent name                :
        File size                    : 98443 bytes
        I-node number                : 290850
        No. directory entries        : 0
        Permission (octal)           : 0644
        Link count                   : 1
        Ownership                    : UID=0, GID=0
        Preferred I/O block size     : 4096 bytes
        Blocks allocated             : 200
        Last status change           : Tue, 21 Nov 17 21:28:18 +0530
        Last file access             : Thu, 28 Dec 17 00:53:27 +0530
        Last file modification       : Tue, 21 Nov 17 21:28:18 +0530
        Hash                         : 9f0312d130016d103aa5fc9d16a2437e

Stats for /home/lab/linux-4.14-rc8:
        Elapsed time     : 1.305767 s
        Start time       : Sun, 07 Jan 18 03:42:39 +0530
        Root hash        : 434e93111ad6f9335bb4954bc8f4eca4
        Hash type        : md5
        Depth            : 8
        Total,
                size           : 66850916 bytes
                entries        : 12484
                directories    : 763
                regular files  : 11715
                symlinks       : 6
                block devices  : 0
                char devices   : 0
                sockets        : 0
                FIFOs/pipes    : 0
2
six-k

そのためのpythonスクリプトがあります:

http://code.activestate.com/recipes/576973-getting-the-sha-1-or-md5-hash-of-a-directory/

アルファベット順を変更せずにファイルの名前を変更すると、ハッシュスクリプトはそれを検出しません。ただし、ファイルの順序やファイルの内容を変更すると、スクリプトを実行すると以前とは異なるハッシュが得られます。

2
Kingdon

これを実現する別のツール:

http://md5deep.sourceforge.net/

サウンドとして:md5sumに似ていますが、再帰的であり、その他の機能もあります。

1
Jack

個々のファイルの結果をsort(ハッシュを変更するための単なるファイルの並べ替えを防ぐため)を介して、md5sumまたはsha1sumのいずれかを選択します。

1
Rafał Dowgird

これを行うGroovyスクリプトを作成しました。

import Java.security.MessageDigest

public static String generateDigest(File file, String digest, int paddedLength){
    MessageDigest md = MessageDigest.getInstance(digest)
    md.reset()
    def files = []
    def directories = []

    if(file.isDirectory()){
        file.eachFileRecurse(){sf ->
            if(sf.isFile()){
                files.add(sf)
            }
            else{
                directories.add(file.toURI().relativize(sf.toURI()).toString())
            }
        }
    }
    else if(file.isFile()){
        files.add(file)
    }

    files.sort({a, b -> return a.getAbsolutePath() <=> b.getAbsolutePath()})
    directories.sort()

    files.each(){f ->
        println file.toURI().relativize(f.toURI()).toString()
        f.withInputStream(){is ->
            byte[] buffer = new byte[8192]
            int read = 0
            while((read = is.read(buffer)) > 0){
                md.update(buffer, 0, read)
            }
        }
    }

    directories.each(){d ->
        println d
        md.update(d.getBytes())
    }

    byte[] digestBytes = md.digest()
    BigInteger bigInt = new BigInteger(1, digestBytes)
    return bigInt.toString(16).padLeft(paddedLength, '0')
}

println "\n${generateDigest(new File(args[0]), 'SHA-256', 64)}"

使用方法をカスタマイズして、各ファイルの印刷を回避したり、メッセージダイジェストを変更したり、ディレクトリハッシュを削除したりできます。NISTテストデータに対してテストしたところ、期待どおりに機能します。 http://www.nsrl.nist.gov/testdata/

gary-macbook:Scripts garypaduana$ groovy dirHash.groovy /Users/garypaduana/.config
.DS_Store
configstore/bower-github.yml
configstore/insight-bower.json
configstore/update-notifier-bower.json
filezilla/filezilla.xml
filezilla/layout.xml
filezilla/lockfile
filezilla/queue.sqlite3
filezilla/recentservers.xml
filezilla/sitemanager.xml
gtk-2.0/gtkfilechooser.ini
a/
configstore/
filezilla/
gtk-2.0/
lftp/
menus/
menus/applications-merged/

79de5e583734ca40ff651a3d9a54d106b52e94f1f8c2cd7133ca3bbddc0c6758
1
haventchecked

Python 3のシンプルで短いバリアントは、サイズの小さいファイル(ソースツリーなど、すべてのファイルが個別にRAM =簡単)、他のソリューションのアイデアに基づいて、空のディレクトリを無視します:

import os, hashlib

def hash_for_directory(path, hashfunc=hashlib.sha1):                                                                                            
    filenames = sorted(os.path.join(dp, fn) for dp, _, fns in os.walk(path) for fn in fns)         
    index = '\n'.join('{}={}'.format(os.path.relpath(fn, path), hashfunc(open(fn, 'rb').read()).hexdigest()) for fn in filenames)               
    return hashfunc(index.encode('utf-8')).hexdigest()                          

それはこのように動作します:

  1. ディレクトリ内のすべてのファイルを再帰的に検索し、名前で並べ替えます
  2. すべてのファイルのハッシュ(デフォルト:SHA-1)を計算します(ファイル全体をメモリに読み込みます)
  3. 「filename = hash」行でテキストインデックスを作成します
  4. そのインデックスをエンコードしてUTF-8バイト文字列に戻し、ハッシュします

SHA-1がお茶ではない場合、2番目のパラメーターとして 異なるハッシュ関数 を渡すことができます。

0
Thomas Perl

2つのステップで作成してみてください。

  1. フォルダー内のすべてのファイルのハッシュを含むファイルを作成します
  2. このファイルをハッシュする

そのようです:

# for FILE in `find /folder/of/stuff -type f | sort`; do sha1sum $FILE >> hashes; done
# sha1sum hashes

または、一度にすべてを実行します。

# cat `find /folder/of/stuff -type f | sort` | sha1sum
0
Joao da Silva

あなたは出来る sha1sumハッシュ値のリストを生成してからsha1sumそのリストは、あなたが何を達成したいかによって異なります。

0
Ronny Vindenes

ファイルの変更については、ディレクトリ全体をチェックインする必要がありました。

ただし、タイムスタンプ、ディレクトリの所有権を除外します。

目標は、ファイルが同一である場合、どこでも同一の合計を取得することです。

ファイル以外、またはそれらへの変更に関係なく、他のマシンにホストされているものを含みます。

md5sum * | md5sum | cut -d' ' -f1

ファイルごとにハッシュのリストを生成し、それらのハッシュを1つに連結します。

これは、tarメソッドよりもはるかに高速です。

ハッシュ内のより強力なプライバシーの場合、同じレシピでsha512sumを使用できます。

sha512sum * | sha512sum | cut -d' ' -f1

ハッシュもsha512sumを使用してどこでも同じですが、それを逆にする既知の方法はありません。

0
NVRM

これがgitリポジトリであり、.gitignore内のファイルを無視する場合、これを使用できます。

git ls-files <your_directory> | xargs sha256sum | cut -d" " -f1 | sha256sum | cut -d" " -f1

これは私にとってうまく機能しています。

0
ndbroadbent