6

今日、md5 ハッシュを使用して、重複ファイルを削除する Bash スクリプトを作成する必要がありました。これらのハッシュをファイルとして一時ディレクトリに保存しました。

for i in * ; do
    hash=$(md5sum /tmp/msg | cut -d " " -f1) ;
    if [ -f /tmp/hashes/$hash ] ;
    then
        echo "Deleted $i" ;
        mv $i /tmp/deleted ;
    else
        touch /tmp/hashes/$hash ;
    fi ;
done

それは完璧に機能しましたが、疑問に思いました: それは時間効率の良い方法ですか? 最初はMD5ハッシュをファイルに保存することを考えていましたが、「いいえ、このファイルに特定のMD5が含まれているかどうかを確認するには、毎回完全に再読み取りする必要があるため」と考えました。さて、「ディレクトリにファイルを作成する」方法を使用する場合も同じですか?同じディレクトリに多数のファイルがある場合、Bash [ -f ] は線形または準一定の複雑さをチェックしますか?

ファイルシステムに依存する場合、tmpfs の複雑さは何ですか?

4

4 に答える 4

2

私は仕事に適したツールを使用するのが好きです。この場合、重複ファイルのみを表示する必要があります。私は自由に使える数千のファイルに対してこれをテストしましたが、ファイルを再読み込みしても問題はないようでした。さらに、何百もの重複ファイルがあることに気付きました。ハッシュを別々のファイルに保存してからこの大量のファイルを処理すると、1 つのディレクトリに約 10,000 個のハッシュ ファイルがあると、私のシステムはゆっくりと進みます。すべてのハッシュを 1 つのファイルにまとめることで、これが大幅に高速化されました。

# This uses md5deep.  An alternate is presented later.
md5deep -r some_folder > hashes.txt

# If you do not have md5deep
find . -type f -exec md5sum \{\} \;

これにより、すべてのハッシュが得られます。

cut -b -32 hashes.txt | sort | uniq -d > dupe_hashes.txt

これを使用cutして、各ファイルのハッシュを取得し、ハッシュを並べ替えてから、重複したハッシュを見つけます。それらはdupe_hashes.txt、ファイル名が添付されていない状態で書き込まれます。次に、ハッシュをファイルにマッピングする必要があります。

(for hash in $(cat dupe_hashes.txt); do
    grep "^$hash" hashes.txt | tail -n +2 | cut -b 35-
done) > dupe_files.txt

これは私にとってゆっくりと実行されているようには見えません。Linux カーネルは、このようなファイルを頻繁にディスクから読み取るのではなく、メモリに保持するという非常に優れた仕事をします。これを強制的にメモリに入れたい場合は、/dev/shm/hashes.txt代わりにhashes.txt. 私のテストでは不要であることがわかりました。

これにより、重複しているすべてのファイルが得られます。ここまでは順調ですね。おそらく、このリストを確認する必要があります。元のものもリストしたい場合はtail -n +2 |、コマンドからビットを削除してください。

リストされたすべてのファイルを削除できることに満足している場合は、xargs にパイプすることができます。これにより、ファイルが 50 個のグループで削除されます。

xargs -L 50 rm < dupe_files.txt
于 2015-09-30T19:43:45.960 に答える
0

ハッシュを含むファイルの内容を読み取るか、ハッシュであるファイル名のディレクトリでハッシュを見つけるかの選択は、基本的に「カーネルがディレクトリを読み取るのが速いか、プログラムがファイルを読み取るのが速いか」に帰着します。どちらもハッシュごとに線形検索を行うため、最終的にはほとんど同じ動作になります。おそらく、カーネルはもう少し高速であるべきだと主張できますが、マージンは大きくありません。ほとんどの場合、ハッシュが存在しないため、線形検索は徹底的に行われることに注意してください (多数の重複ファイルがない限り)。したがって、数千のファイルを処理している場合、検索では全体で数百万のエントリが処理されます。これは 2 次動作です。

数百または数千のファイルがある場合は、おそらく 2 レベルの階層を使用したほうがよいでしょう。たとえば、2 文字のサブディレクトリ 00 .. FF を含むディレクトリと、残りの名前 (またはフルネーム) をサブディレクトリに配置します。たとえば、この手法のマイナーなバリエーションがterminfoディレクトリで使用されます。利点は、ファイルが存在するかどうかを調べるために、カーネルが比較的小さなディレクトリを読み取るだけでよいことです。

于 2015-08-04T22:45:58.370 に答える