So entfernen Sie doppelte Dateien mit bash

10

Ich habe einen Ordner mit doppelten (von md5sum( md5auf einem Mac)) Dateien, und ich möchte einen Job planen, um alle gefundenen zu entfernen.

Ich bin jedoch nicht sicher, wie das geht. Was ich bisher habe:

md5 -r * | sort

Welches gibt so etwas aus:

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

Wie kann ich basierend auf dem MD5 der Datei verarbeiten, um Duplikate zu entfernen? Es ist mir egal, welches "Original" ich behalte - aber ich möchte nur eines behalten.

Sollte ich das anders angehen?

Labyrinth
quelle
3
Es gibt bereits einen fdupesBefehl, der dies ausführt ... Ich bin mir nicht sicher, auf welcher Distribution Sie sich befinden, aber er befindet sich in einem Debian-Paket mit demselben Namen. Außerdem ist MD5 heutzutage ein ziemlich schwacher Hash. Sie möchten wahrscheinlich verwenden sha256sum oder besser sha512sum(was auf normaler PC-Hardware eigentlich schneller sein sollte )
derobert
1
@derobert - Ich weiß, MD5 ist ein schwacher Hash, aber es ist einfach und gut genug, um kleine Dateien zu vergleichen :)
Warren
Nun, MD5-Kollisionen sind bekannt und können mit relativ wenig CPU-Leistung generiert werden, und es gibt einen Befehl, den Sie ersetzen können, um stattdessen SHA-512 zu verwenden, also ...
derobert
@derobert - Ich verstehe, dass es potenzielle Nachteile bei der Verwendung von md5 gibt .. aber es ist mehr als ausreichend in diesem Szenario (um sicherzustellen, dass ich keine doppelten Dateien in einem bestimmten Verzeichnis habe)
Warren
1
Meinetwegen. Hauptpunkt des Kommentars war es, auf fdupes hinzuweisen.
Derobert

Antworten:

3

Ich arbeite unter Linux, was bedeutet, dass dies der Befehl ist, der Folgendes md5sumausgibt:

> 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

Jetzt mit awkund xargsder Befehl wäre:

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

Der awkTeil wird lasthashmit der leeren Zeichenfolge initialisiert , die keinem Hash entspricht, und prüft dann für jede Zeile, ob der Hash-In lasthashmit dem Hash (erste Spalte) der aktuellen Datei (zweite Spalte) übereinstimmt . Wenn ja, wird es ausgedruckt. Am Ende jedes Schritts wird lasthashder Hash der aktuellen Datei festgelegt (Sie können dies so einschränken, dass er nur festgelegt wird, wenn die Hashes unterschiedlich sind. Dies sollte jedoch eine untergeordnete Rolle spielen, insbesondere wenn Sie nicht über viele übereinstimmende Dateien verfügen). Die Dateinamen awk ausspuckt zugeführt werden rmmit xargs, was im Grunde ruft rmmit dem, was das awkTeil uns gibt.

Sie müssen wahrscheinlich vorher Verzeichnisse filtern md5sum *.

Bearbeiten:

Mit der Marcins-Methode können Sie auch diese verwenden:

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

Dies wird von der Dateiliste abgezogen, die durch lsden ersten Dateinamen jedes eindeutigen Hashs ausgewählt wurde, der durch ausgewählt wurde md5sum * | sort -k1 | uniq -w 32 | awk '{print $2}'.

Tristan Storch
quelle
1
Dank: md5 -r * | sort -t ' ' -k 4 -r | awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | xargs rmist der Ruf auf O X (pro @ Stephen Kitt ‚s Vorschlag, ich ein lege echo 'will remove 'am Ende , bevor es mit dem Versuch rm)
warren
Sie sollten Ihre Frage dann wahrscheinlich bearbeiten, da die angegebene Lösung nicht mit der von Ihnen angegebenen Beispielausgabe übereinstimmt.
Stephen Kitt
1
Und Sie sollten ändern sort -t ' ' -k 4 -rzu sort.
Tristan Storch
@TristanStorch - guter Ort :)
Warren
Dies setzt voraus, dass Ihre Dateinamen keine Leerzeichen enthalten, was unter allen Umständen eine gefährliche Annahme ist. (Und vor allem, wenn das OP einen Mac verwendet. Ich wage es, einen Mac zu finden, jeden Mac, der überhaupt keine Leerzeichen enthält.) :)
Wildcard
7

Sie können doppelte Dateien mit dem folgenden Befehl identifizieren:

md5sum * | sort -k1 | uniq -w 32 -d
Marcin
quelle
1
Dies gibt nur eine Datei für jeden Satz von Duplikaten aus. Wenn Sie alle Duplikate löschen und nur eines behalten möchten, können Sie die mit diesem Befehl erhaltenen behalten und den Rest löschen
Golimar
2

Als Antwort auf diese ähnliche Frage bin ich auf fdupes gestoßen : /superuser/386199/how-to-remove-duplicated-files-in-a-directory

Ich konnte apt-get install fdupesauf Ubuntu. Sie werden auf jeden Fall die Manpage lesen wollen. In meinem Fall konnte ich die gewünschten Ergebnisse wie folgt erzielen:

fdupes -qdN -r /ops/backup/

Darin heißt es: "Durchsuchen Sie rekursiv / ops / backup und finden Sie alle doppelten Dateien: Behalten Sie die erste Kopie einer bestimmten Datei und entfernen Sie den Rest stillschweigend." Dies macht es sehr einfach, mehrere Speicherauszüge einer Datenbank mit seltenem Schreibvorgang zu speichern.

Dannyman
quelle
1

Wenn Sie es eilig haben (oder viele Dateien haben) und den Overhead einer Art vermeiden möchten (es braucht Zeit), aber den Speicher-Overhead einer Hash-Tabelle nicht stören (oder wenn Sie viel RAM mit Ihren Losen haben) von Dateien),

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: Finden Sie alle Dateien und geben Sie sie mit nullterminierten Namen aus

xargs -0 md5sum: Hashes parallel berechnen ( -nmax-args und -Pmax-procs nach Wunsch anpassen , siehe man xargs)

awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }': Wenn die awk-Hashtabelle einen Eintrag enthält, der die aktuell angezeigte md5sum enthält, drucken Sie den aktuell angezeigten Dateinamen nullterminiert aus. Andernfalls fügen Sie den Dateinamen zur Hash-Tabelle hinzu.

xargs -0 rm: Nehmen Sie die eingefügten nullterminierten Zeichenfolgen und senden Sie sie an rm.

Dies ist viel schneller als fdupes.

Wenn Sie einen Dateinamen haben, der eine neue Zeile enthält, wird awk diese wahrscheinlich an der neuen Zeile abschneiden, da md5sum Datensätze auch durch Zeilenumbrüche trennt.

Dies basiert auf /programming/11532157/remove-duplicate-lines-without-sorting und /programming/9133315/how-can-i-output-null-terminated- Strings-in-Awk

Alex
quelle
1
md5sum * | sort -k1 | uniq -w 32 -d | cut -d' ' -f3 | xargs -I{} sh -c 'rm {}'
  1. nimm alle md5 Werte
  2. sortiere sie so, dass Dupes für uniq sequentiell sind
  3. Führen Sie uniq aus, um nur Dupes auszugeben
  4. Schneiden Sie den Dateinamen aus der Zeile mit dem Wert md5
  5. Rufen Sie wiederholt delete für die Dateinamen auf
Carter Cole
quelle
0
comm -13 <(md5sum * | sort | uniq -w 32 -d) <(md5sum * | sort | uniq -w 32 -D) | cut -f 3- -d" " | xargs -d '\n' rm

Eigenschaften:

  • Funktioniert immer noch, wenn mehr als ein Duplikat pro Datei vorhanden ist
  • Funktioniert immer noch, wenn Dateinamen Leerzeichen enthalten
  • Funktioniert immer noch, wenn Sie lsmit einer Sortierung oder einem Alias ​​versehen haben--color=always
Alex Lamson
quelle