UNIX/Linuxで大きなファイルとストリームのチェックサムを実行したいのですが、ファイル/ストリームのすべての大部分、1 MBごと、または10MBごとに多くのチェックサムを取得したいと考えています。
たとえば、ディスクイメージ、圧縮ディスクイメージ、および元のディスクのコピーがあります。画像の一部が変更される場合があります。ディスクは50GBで、1MBのブロックが約50000個あります。したがって、すべてのファイルについて、変更の概要を取得するために50 000md5sumまたはsha1sumsを取得したいと思います。単一のmd5sumは、変更オフセットを見つけるのに役立ちません。
このタスクは、オフセットを計算し、ファイルの1MBの部分ごとに選択(スキップ)して、bashのdd
ループでfor
ツールを使用することで、非圧縮ディスクイメージに対して簡単です。ディスクと同じ:
for a in `seq 1 50000`; do echo -n "$a: "; dd if=image.src bs=1M count=1 skip=$a | md5sum; done
しかし今、私はそれをディスクに解凍せずに圧縮された画像と圧縮されていない画像を比較したいと思います。 7z
unpackerがあり、最大150〜200 MB/sの高速でイメージをstdoutに解凍できます(オプション7z e -so image.7z |
)。しかし、すべてのファイル部分のmd5sumを取得するために、|
シンボルの後に何を書くことができますか。
このPerlスクリプトのような単純なものでおそらく十分でしょう。
$amount = 1_000_000;
while (read(STDIN, $buffer, $amount) > 0) {
open MD5, "|md5";
print MD5 $buffer;
close MD5;
}
これをfoo.pl
に入れ、パイプラインの最後でPerl foo.pl
として呼び出します。
split from coreutils(ほとんどのLinuxディストリビューションのデフォルト)には--filter
使用できるオプション:
7z e -so image.7z | split -b 1000000 --filter=md5sum
あなたはこの種の ツール を探しているように私には思えます。
BigSyncのReadmeファイルから:
Bigsyncは、単一の大きなファイルを低速の宛先(ネットワークメディアや安価なNASなど)に段階的にバックアップするためのツールです。 bigsyncの最も一般的なケースは、ディスクイメージ、仮想OS、暗号化されたボリューム、およびrawデバイスです。
Bigsyncは、ソースファイルをチャンクで読み取り、それぞれのチェックサムを計算します。以前に保存された宛先ファイルの値と比較し、チェックサムが異なる場合は変更されたチャンクを上書きします。
このようにして、bigsyncの存在の要点である低速のターゲットメディアへのアクセスを最小限に抑えます。
rhash
ツール(librhash
ライブラリ)を使用して、小さな1MBのハッシャーを作成するのは簡単でした。標準入力ストリームの各1MB部分のチェックサムを作成する単純なPerlスクリプトがあります。が必要だ Crypt::Rhash
cpan
からのバインディング:
$ cpan
(cpan) install Crypt::Rhash
$ cat rhash1M.pl
#!/usr/bin/Perl
# Compute md5 and sha1 sum of every 1 MB part of stream
use strict;
use local::lib;
use Crypt::Rhash;
my ($buf, $len, $i);
my $r=Crypt::Rhash->new(RHASH_MD5|RHASH_SHA1);
# we can add more hashes, like RHASH_TIGER etc
binmode STDIN;
$i=0;
while($len= read STDIN,$buf,1024*1024){
print "$i+$len: \t"; # print offset
$r->update($buf);
print "md5:",$r->hash(RHASH_MD5), " sha1:", $r->hash(RHASH_SHA1),"\n";
$r->reset(); # reset hash calculator
$i+=$len;
}
このパブリックドメインスクリプトは、10進オフセットを出力し、次に+
、次にブロックサイズ、次にmd5とsha1の入力の合計。
たとえば、2MBのゼロには合計があります。
$ dd if=/dev/zero of=zerofile bs=1M count=2
$ ./rhash1M.pl < zerofile
0+1048576: md5:b6d81b360a5672d80c27430f39153e2c sha1:3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
1048576+1048576: md5:b6d81b360a5672d80c27430f39153e2c sha1:3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
rsync
はこのように機能し、チェックサムを計算して、何かを送信する前にファイルの一部に違いがあるかどうかを確認します。
ファイルサイズに制限があるとは聞いたことがありませんが、これほど大きなファイルでどれだけうまく機能するかはわかりません。
出力をこのPython 2スクリプト、たとえば7z e -so image.7z | python md5sum.py
:
import sys, hashlib
CHUNK_SIZE = 1000 * 1000
for chunk in iter(lambda: sys.stdin.read(CHUNK_SIZE), ''):
print hashlib.new('md5', chunk).hexdigest()