bashを使用して重複ファイルを削除する方法


10

md5summd5Macでは)ファイルが重複しているフォルダーがあり、 見つかったジョブを削除するようにスケジュールされたジョブ。

しかし、私はこれを行う方法にこだわっています。これまでのところ:

md5 -r * | sort

これは次のようなものを出力します:

04c5d52b7acdfbecd5f3bdd8a39bf8fb gordondam_en-au11915031300_1366x768.jpg
1e88c6899920d2c192897c886e764fc2 fortbourtange_zh-cn9788197909_1366x768.jpg
266ea304b15bf4a5650f95cf385b16de nebraskasupercell_fr-fr11286079811_1366x768.jpg
324735b755c40d332213899fa545c463 grossescheidegg_en-us10868142387_1366x768.jpg
3993028fcea692328e097de50b26f540 Soyuz Spacecraft Rolled Out For Launch of One Year Crew.png
677bcd6006a305f4601bfb27699403b0 lechaustria_zh-cn7190263094_1366x768.jpg
80d03451b88ec29bff7d48f292a25ce6 ontariosunrise_en-ca10284703762_1366x768.jpg
b6d9d24531bc62d2a26244d24624c4b1 manateeday_row10617199289_1366x768.jpg
ca1486dbdb31ef6af83e5a40809ec561 Grueling Coursework.jpg
cdf26393577ac2a61b6ce85d22daed24 Star trails over Mauna Kea.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x768.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x7682.jpg

ファイルのMD5に基づいて処理して重複を削除するにはどうすればよいですか?どの「オリジナル」を保持するかは特に気にしませんが、保持したいのは1つだけです。

これに別の方法でアプローチする必要がありますか?


3
fdupesこれを実行するコマンドはすでに存在します...現在どのディストリビューションにいるかはわかりませんが、同じ名前のDebianパッケージに含まれています。また、最近のMD5はかなり弱いハッシュです。あなたはおそらく使いたいsha256sum か、もっと良くしたいでしょうsha512sum(実際には通常のPCハードウェアではより速いはずです)
derobert

1
@derobert-MD5は弱いハッシュですが、小さいファイルを比較するのに十分でシンプルです:)
warren

まあ、MD5コリジョンは既知であり、かなり適度な量のCPUパワーで生成可能です。代わりにSHA-512を使用するために代用できるコマンドがあるので...
derobert

@derobert-私はmd5を使用することの潜在的なマイナスがあることを理解しています..しかし、これはこのシナリオでは十分すぎる(特定のディレクトリに重複ファイルがないことを確認したい)
warren

1
けっこうだ。コメントの主なポイントは、fdupeを指摘することでした。
derobert、2015年

回答:


3

私はLinuxで作業してmd5sumいます。つまり、次のコマンドが出力されます。

> md5sum *
d41d8cd98f00b204e9800998ecf8427e  file_1
d41d8cd98f00b204e9800998ecf8427e  file_10
d41d8cd98f00b204e9800998ecf8427e  file_2
d41d8cd98f00b204e9800998ecf8427e  file_3
d41d8cd98f00b204e9800998ecf8427e  file_4
d41d8cd98f00b204e9800998ecf8427e  file_5
d41d8cd98f00b204e9800998ecf8427e  file_6
d41d8cd98f00b204e9800998ecf8427e  file_7
d41d8cd98f00b204e9800998ecf8427e  file_8
d41d8cd98f00b204e9800998ecf8427e  file_9
b026324c6904b2a9cb4b88d6d61c81d1  other_file_1
31d30eea8d0968d6458e0ad0027c9f80  other_file_10
26ab0db90d72e28ad0ba1e22ee510510  other_file_2
6d7fce9fee471194aa8b5b6e47267f03  other_file_3
48a24b70a0b376535542b996af517398  other_file_4
1dcca23355272056f04fe8bf20edfce0  other_file_5
9ae0ea9e3c9c6e1b9b6252c8395efdc1  other_file_6
84bc3da1b3e33a18e8d5e1bdd7a18d7a  other_file_7
c30f7472766d25af1dc80b3ffc9a58c7  other_file_8
7c5aba41f53293b712fd86d08ed5b36e  other_file_9

これawkxargs、コマンドは次のようになります。

md5sum * | \
sort | \
awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | \
xargs rm

awk一部の初期化lasthashの任意のハッシュと一致しなくなり、空の文字列と、各ラインのために、次にチェックでハッシュがあればlasthash、現在のファイル(第2カラム)のハッシュ(最初の列)と同じです。ある場合は、印刷します。すべてのステップの最後にlasthash、現在のファイルのハッシュに設定されます(ハッシュが異なる場合にのみ設定されるように制限できますが、一致するファイルが多くない場合は特に重要ではありません)。awkが吐き出すファイル名は、によって供給さrmれますxargs。これは基本的にrmawkパーツが提供するものを呼び出します。

おそらく、前にディレクトリをフィルタリングする必要がありますmd5sum *

編集:

Marcinsメソッドを使用すると、これも使用できます。

comm -1 -2 \
  <(ls) | \
  <(md5sum * | \
    sort -k1 | \
    uniq -w 32 | \
    awk '{print $2}' | \
    sort) \
xargs rm

これは、によって取得されlsた各一意のハッシュの最初のファイル名によって取得されたファイルリストから減算しmd5sum * | sort -k1 | uniq -w 32 | awk '{print $2}'ます。


1
感謝:md5 -r * | sort -t ' ' -k 4 -r | awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | xargs rmOS Xでの呼び出しです(@ Stephen Kittの提案に従って、私はecho 'will remove 'それを試す前に最後にを付けましたrm
ウォーレン

おそらくあなたの質問を編集するべきです。なぜなら、与えられた解決策はあなたが与えた出力例と一致しないからです。
Stephen Kitt 2015年

1
そして、に変更sort -t ' ' -k 4 -rする必要がありsortます。
Tristan Storch

@TristanStorch-良いスポット:)
ウォーレン

これは、ファイル名にスペースがないことを前提としています。これは、いかなる状況でも危険な前提です。(特に、OPがMacを使用していることを考えると、スペースを含むファイル名がまったくないMac、すべてのMacを見つけてみてください。):)
ワイルドカード

7

次のコマンドを使用して、重複ファイルを識別できます。

md5sum * | sort -k1 | uniq -w 32 -d

1
これにより、重複のセットごとに1つのファイルのみが出力されます。すべての重複を削除して1つだけ残したい場合は、このコマンドで取得したものを残して、残りを削除できます
golimar

2

私はこの同様の質問への答えとしてfdupesに出くわしました:https : //superuser.com/questions/386199/how-to-remove-duplicated-files-in-a-directory

apt-get install fdupesUbuntuでできました。あなたは間違いなくマニュアルページを読みたくなるでしょう。私の場合、次のような目的の結果を得ることができました:

fdupes -qdN -r /ops/backup/

これは、「/ ops / backupを再帰的に調べて、すべての重複ファイルを見つける:特定のファイルの最初のコピーを保持し、残りを静かに削除する」と述べています。これにより、書き込み頻度の低いデータベースのいくつかのダンプを非常に簡単に保持できます。


1

急いでいる(またはファイルがたくさんある)場合、ソートのオーバーヘッドを避けたい(時間がかかる)が、ハッシュテーブルのメモリオーバーヘッドを気にしない(または、たくさんのRAMがある場合)ファイルの)、

find . -type f -print0 | xargs -0 md5sum | awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }' | xargs -0 rm

find . -type f -print0:すべてのファイルを検索し、ヌル終了名で出力します

xargs -0 md5sum:ハッシュを並列で計算します(必要に応じて-nmax-argsと-Pmax-procsを調整します。を参照してくださいman xargs

awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }':現在見ているmd5sumを含むawkハッシュテーブルにエントリがある場合、現在見ているファイル名をnullで終了して出力します。それ以外の場合は、ファイル名をハッシュテーブルに追加します。

xargs -0 rm:パイプインされたnullで終了する文字列を取り、それらをrmに送信します。

これはfdupeよりもはるかに高速です。

改行を含むファイル名がある場合、md5sumもレコードを改行で区切るため、awkはおそらく改行で切り捨てます。

これは/programming/11532157/remove-duplicate-lines-without-sortingおよび/programming/9133315/how-can-i-output-null-terminated-に基づいていますひもでつなぐ


1
md5sum * | sort -k1 | uniq -w 32 -d | cut -d' ' -f3 | xargs -I{} sh -c 'rm {}'
  1. すべてのmd5値を取ります
  2. それらを並べ替えて、unipのdupeが順次になるようにします
  3. uniqを実行してdupeのみを出力する
  4. md5値を持つ行からファイル名を切り取ります
  5. ファイル名に対して繰り返しdeleteを呼び出す

0
comm -13 <(md5sum * | sort | uniq -w 32 -d) <(md5sum * | sort | uniq -w 32 -D) | cut -f 3- -d" " | xargs -d '\n' rm

特徴:

  • ファイルごとに複数の重複がある場合でも機能します
  • ファイル名にスペースがある場合でも機能します
  • lsソートで別名を付けた場合や、--color=always
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.