Entfernen Sie doppelte Dateien, indem Sie sie mit MD5 RECURSIVELY vergleichen

553
mandy

Ich möchte doppelte Dateien basierend auf ihrem MD5-Wert löschen. Ich habe das Skript bereits unten, aber wie modifiziere ich es, damit es rekursiv funktioniert?

So habe ich zum Beispiel Ordner mit 3 Unterordnern A B C

Ich möchte, dass ALLE Dateien in ./ ./A/ ./B/ ./C/ auf ihren MD5 geprüft und miteinander verglichen werden. Wenn eine positive Übereinstimmung gefunden wird, löschen Sie einfach beide Übereinstimmungen. Am Ende existieren keine Duplikate mehr. Es ist mir egal, welches Match zuerst gelöscht wird.

Ich hoffe, ich habe zum Ausdruck gebracht, was ich klar genug erreichen muss, wenn nicht, lassen Sie es mich bitte wissen :)

#!/bin/bash while true do echo "Enter the directory:" read directory if [ -d $directory ]; then break else echo "Invalid directory" fi done  for FILE in `ls $directory` do if [ ! -f $FILE ]; then break; fi h=`md5sum $directory/$FILE | awk '{ print $1 }'` for f in `ls $directory` do if [ -f $f ] && [ $FILE != $f ]; then s=`md5sum $directory/$f | awk '{ print $1 }'` if [ "$s" = "$h" ]; then echo Removing $f rm -rf $directory/$f fi fi done done 
0
Ist dies eine Skript-Schreibübung? Es gibt Tools (z. B. "jdupes" oder "fdupes" für Linux), mit denen Duplikate erkannt, Hardlinks erstellt oder übermäßige Kopien gelöscht werden. Kamil Maciorowski vor 5 Jahren 2
Haben Sie versucht, `find` zu verwenden? Wahrscheinlich lohnt es sich auch, `while read FILE` anstelle von` for FILE in $ (...) `zu verwenden, um umfangreiche Listen zu bearbeiten. Attie vor 5 Jahren 0
Danke für deine Antworten. Das Skript soll unter Windows und nicht unter Linux funktionieren. Ich glaube ich bin am falschen Ort mandy vor 5 Jahren 0
Sie sind an einem guten Ort, bearbeiten Sie einfach die Frage und geben Sie Ihre Umgebung (WSL? Cygwin?) Und den Zweck an (Aufgabe erledigen, egal mit welchem ​​Tool? Oder nur mit Bash erledigen? Usw.). Kamil Maciorowski vor 5 Jahren 2
Das Skript, das Sie zeigen, ist für Linux ... Aber die Leistung ist miserabel. Seine Leistung ist O (n²), dh doppelt so viele Dateien werden viermal länger dauern. Für 100 Dateien wird md5sum 100.000 mal ausgeführt !!! . Ich bezweifle, dass es jemals wirklich benutzt wurde. xenoid vor 5 Jahren 1
@xenoid "_for Linux_" -> "_for bash_" Attie vor 5 Jahren 0
@attie Seit wann ist `md5sum` eine bash eingebaut :) xenoid vor 5 Jahren 0
@xenoid was? es ist nicht ... seit wann war es "_linux only_"? OP hat ein "_bash-Skript" bereitgestellt, das sich aus dem Shebang und dem Tag ergibt. Attie vor 5 Jahren 0

2 Antworten auf die Frage

1
StephenG

Zunächst ein Nachteil: Die Annahme einer Identität anhand einer Prüfsumme ist sehr gefährlich. Nicht empfohlen.

Die Verwendung einer Prüfsumme als Filter zum Entfernen bestimmter Nicht-Duplikate ist in Ordnung.

Wenn ich das mache, gehe ich so vor:

  1. Erstellen Sie eine Liste von Dateien nach Länge (Länge, vollständiger Pfadname).

  2. Scannen Sie diese Liste nach potenziellen doppelten Längen.

  3. Übereinstimmungen sind mögliche Duplikate, und ich würde die verdächtigen Dateien nach Möglichkeit richtig vergleichen.

Der Grund für die Verwendung von Längen ist, dass diese Informationen sehr schnell verfügbar sind, ohne die Datei Byte für Byte zu scannen, da sie normalerweise in den Dateisystemstatistiken für einen schnellen Zugriff gespeichert werden.

Sie können eine weitere Stufe hinzufügen, in der die Prüfsummen (für Dateien mit ähnlicher Länge) verglichen werden, wenn Sie der Meinung sind, dass dies schneller ist als der direkte Vergleich von Dateien, indem Sie einen ähnlichen Ansatz verwenden (Prüfsummen werden einmal berechnet). Verwenden Sie einen ähnlichen Ansatz (beginnen Sie mit der Liste der übereinstimmenden Längen und berechnen Sie die Prüfsummen dafür).

Von der Prüfsummenberechnung profitieren Sie nur, wenn mehrere Dateien mit der gleichen Länge vorhanden sind. Selbst dann, wenn Byte für Byte ein direkter Vergleich erfolgt, werden sehr wahrscheinlich sehr schnell keine Übereinstimmungen gefunden.

Ich stimme zu, die Längen zuerst zu überprüfen. Die Verwendung von Hashes ist jedoch besser: Die Chancen, zwei identische MD5-Summen für verschiedene Dateien zu haben, sind äußerst gering, und Sie könnten bessere Hash-Algorithmen verwenden. Wenn Sie große Dateien haben, ist die Prüfsumme besser, da Sie die Datei nur einmal lesen. Angenommen, Sie haben drei 1-GB-Videos der gleichen Größe, mit Prüfsummen lesen Sie 3 GB, und Byte für Byte vergleichen Sie mit 6 GB. Der byteweise Vergleich ist auch O (n²), wenn der Vergleich von Hashes linear sein kann. xenoid vor 5 Jahren 0
Die beste Vorgehensweise wäre, sich niemals auf eine Prüfsumme für die Identität der Dateien zu verlassen. Ich würde mehrere Hashes (verschiedene Algorithmen) besser in Betracht ziehen, aber letztendlich prüft man wirklich nicht nach einem Duplikat, sondern nach einer Duplikat-Signatur. Hände hoch, die dem CEO erklären wollen, warum diese wichtigen Dateien versehentlich gelöscht wurden. :-) Wenn es keine erheblichen Zeit- / Leistungsbeschränkungen gibt, die das Risiko eines Datenverlusts rechtfertigen, sollten Sie immer eine ordnungsgemäße Überprüfung durchführen. Beachten Sie, dass die Verwendung von Prüfsummen bei allen Risiken das * Löschen * einiger Duplikate * mit sich bringt, aber das ist immer eine sicherere Sache als ein versehentliches Löschen. StephenG vor 5 Jahren 0
Hashes funktionieren gut. Git basiert auf Hashes, ebenso wie eine ganze Reihe von Sicherheitsanwendungen (zum Beispiel das HTTPS-Zertifikat Ihrer Bank oder die Website Ihres Unternehmens). Wenn Sie wirklich paranoid sind, können Sie den Hash mit einem byteweisen Vergleich ergänzen, der linear sein wird, da er jedes Mal Gleichheit findet. xenoid vor 5 Jahren 0
0
Attie

Ich würde stattdessen etwas wie das folgende empfehlen:

find . -type f \ | xargs md5sum \ | sort -k1,1 \ | uniq -Dw32 

Dadurch werden alle duplizierten Dateien in Gruppen von Dateien aufgelistet, die einen identischen MD5-Hash haben.

Achtung, das -w32Argument to uniqvergleicht nur die ersten 32 Zeichen. Wenn Sie die Länge des Hash ändern, müssen Sie dies aktualisieren.


Betrachten Sie den folgenden Baum mit folgendem Inhalt:

./a/1: foo ./a/2: bar ./b/3: hello world ./b/d/5: bar ./c/4: foo 
$ find . -type f \ > | xargs md5sum \ > | sort -k1,1 \ > | uniq -Dw32 c157a79031e1c40f85931829bc5fc552 ./a/2 c157a79031e1c40f85931829bc5fc552 ./b/d/5 d3b07384d113edec49eaa6238ad5ff00 ./a/1 d3b07384d113edec49eaa6238ad5ff00 ./c/4 

Sie können jetzt die Zeilen nacheinander bearbeiten ... jede Zeile mit einem übereinstimmenden Hash an den vorderen Punkten einer Datei, die entdupliziert werden kann.

Wenn Sie sich nicht zu viele Gedanken darüber machen, welche Datei gelöscht wird, funktioniert Folgendes:

find . -type f \ | xargs md5sum \ | sort -k1,1 \ | uniq -Dw32 \ | while read hash file; do  [ "$" == "$" ] && rm -v "$" prev_hash="$";  done 

Beachten Sie, dass MD5 nicht mehr als sicher gilt ... Wenn Sie dies also in einem System verwenden, in dem Benutzer die Kontrolle über Dateien haben, ist es möglich, dass sie eine Kollision erstellen - und somit versehentlich ein legitimes / Ziel entfernen Datei statt Dubletten, wie Sie es sich erhofft hatten. Bevorzugen Sie einen stärkeren Hash wie SHA-256 .