288

2つのファイルに同じデータが含まれているかどうかを確認する必要があるシェルスクリプトがあります。私はこれを多くのファイルに対して行いますが、私のスクリプトでは、diffコマンドがパフォーマンスのボトルネックになっているようです。

行は次のとおりです。

diff -q $dst $new > /dev/null

if ($status) then ...

ファイルを比較するより速い方法、おそらくデフォルトの代わりにカスタムアルゴリズムがあるdiffでしょうか?

4

8 に答える 8

475

私はcmp最初のバイトの違いで止まると信じています:

cmp --silent $old $new || echo "files are different"
于 2012-10-15T17:15:56.240 に答える
69

@AlexHowanskyがこれに「cmp--silent」を使用しているのが好きです。しかし、私はポジティブとネガティブの両方の応答が必要なので、以下を使用します。

cmp --silent file1 file2 && echo '### SUCCESS: Files Are Identical! ###' || echo '### WARNING: Files Are Different! ###'

次に、これをターミナルまたはsshで実行して、ファイルを定数ファイルと照合します。

于 2015-10-01T01:01:55.730 に答える
27

2つのファイルをすばやく安全に比較するには:

if cmp --silent -- "$FILE1" "$FILE2"; then
  echo "files contents are identical"
else
  echo "files differ"
fi

読みやすく、効率的で、以下を含むすべてのファイル名で機能します"` $()

于 2020-09-20T06:45:11.837 に答える
15

私は吸うし、十分な評判ポイントを持っていないので、コメントとしてこの一口を追加することはできません。

ただし、cmpコマンドを使用する場合(および冗長にする必要がない/したくない場合)は、終了ステータスを取得するだけです。cmpマニュアルページによると:

FILEが「-」または欠落している場合は、標準入力を読み取ります。終了ステータスは、入力が同じ場合は0、異なる場合は1、問題がある場合は2です。

したがって、次のようなことができます。

STATUS="$(cmp --silent $FILE1 $FILE2; echo $?)"  # "$?" gives exit status for each comparison

if [[ $STATUS -ne 0 ]]; then  # if status isn't equal to 0, then execute code
    DO A COMMAND ON $FILE1
else
    DO SOMETHING ELSE
fi

編集:みんなのコメントをありがとう!ここでテスト構文を更新しました。ただし、読みやすさ、スタイル、構文の点でこの回答に似たものを探している場合は、Vasiliの回答を使用することをお勧めします。

于 2018-11-28T23:27:21.577 に答える
3

違いのないファイルの場合、過去に読み取った場合でも、どの方法でも両方のファイルを完全に読み取る必要があります。

代替手段はありません。したがって、ある時点でハッシュまたはチェックサムを作成するには、ファイル全体を読み取る必要があります。大きなファイルには時間がかかります。

ファイルメタデータの取得は、大きなファイルを読み取るよりもはるかに高速です。

では、ファイルが異なることを確認するために使用できるファイルメタデータはありますか?ファイルサイズ ?または、ファイルのごく一部を読み取るだけのfileコマンドの結果でさえありますか?

ファイルサイズのサンプルコードフラグメント:

  ls -l $1 $2 | 
  awk 'NR==1{a=$5} NR==2{b=$5} 
       END{val=(a==b)?0 :1; exit( val) }'

[ $? -eq 0 ] && echo 'same' || echo 'different'  

ファイルが同じサイズの場合は、完全なファイル読み取りでスタックします。

于 2012-10-15T18:38:15.063 に答える
2

sha256のようなチェックサムアルゴリズムで比較できます

sha256sum oldFile > oldFile.sha256

echo "$(cat oldFile.sha256) newFile" | sha256sum --check

newFile: OK

ファイルが異なる場合、結果は次のようになります。

newFile: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
于 2020-08-29T11:02:48.227 に答える
1

Raspberry Pi 3B +でいくつかのテストを行って(私はオーバーレイファイルシステムを使用しており、定期的に同期する必要があります)、diff-qとcmp-sについて自分の比較を実行しました。これは/dev/ shm内からのログであるため、ディスクアクセス速度は問題ではないことに注意してください。

[root@mypi shm]# dd if=/dev/urandom of=test.file bs=1M count=100 ; time diff -q test.file test.copy && echo diff true || echo diff false ; time cmp -s test.file test.copy && echo cmp true || echo cmp false ; cp -a test.file test.copy ; time diff -q test.file test.copy && echo diff true || echo diff false; time cmp -s test.file test.copy && echo cmp true || echo cmp false
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 6.2564 s, 16.8 MB/s
Files test.file and test.copy differ

real    0m0.008s
user    0m0.008s
sys     0m0.000s
diff false

real    0m0.009s
user    0m0.007s
sys     0m0.001s
cmp false
cp: overwrite âtest.copyâ? y

real    0m0.966s
user    0m0.447s
sys     0m0.518s
diff true

real    0m0.785s
user    0m0.211s
sys     0m0.573s
cmp true
[root@mypi shm]# pico /root/rwbscripts/utils/squish.sh

私はそれを数回実行しました。cmp -sは、私が使用していたテストボックスで一貫してわずかに短い時間でした。したがって、cmp -sを使用して、2つのファイル間で処理を実行する場合は...

identical (){
  echo "$1" and "$2" are the same.
  echo This is a function, you can put whatever you want in here.
}
different () {
  echo "$1" and "$2" are different.
  echo This is a function, you can put whatever you want in here, too.
}
cmp -s "$FILEA" "$FILEB" && identical "$FILEA" "$FILEB" || different "$FILEA" "$FILEB"
于 2018-11-09T17:53:09.537 に答える
0

cksumコマンドも使用してみてください。

chk1=`cksum <file1> | awk -F" " '{print $1}'`
chk2=`cksum <file2> | awk -F" " '{print $1}'`

if [ $chk1 -eq $chk2 ]
then
  echo "File is identical"
else
  echo "File is not identical"
fi

cksumコマンドは、ファイルのバイト数を出力します。'mancksum'を参照してください。

于 2016-09-23T00:59:59.433 に答える