JayKay
Anmeldungsdatum: 22. Oktober 2005
Beiträge: 111
Wohnort: Lampertheim
|
moinsen *, da ich in der shell mit programmieren eher weniger bewandert bin, gebe ich meine Frage mal an euch weiter, ich hoffe es gibt eine recht einfache Lösung 😉 ich suche eine Möglichkeit, möglichst auf der Konsole, in einem bestimmten Ordner (und Unterordnern) gleiche Dateien zu finden (evtl. auch gleich löschen?), die nicht unbedingt den gleichen Namen haben, vllt. nach Checksumme überprüfen oder so. Gibt es da etwas was man benutzten könnte oder jemand, der weiß wie man das (auch für größere Datenmengen) realisieren könnte. merci ☺ jk
|
comm_a_nder
Anmeldungsdatum: 5. Februar 2006
Beiträge: 2533
Wohnort: Dresden
|
Voraussetzung: Paket md5deep installiert
md5deep -r SUCHVERZEICHNISS | sort -k1,33 | uniq -d -w32 > /tmp/doppelte_dateien && md5deep -r -M /tmp/doppelte_dateien SUCHVERZEICHNISS; rm /tmp/doppelte_dateien €: Vielleicht sollte man es in mehrere Zeilen schreiben, damit es übersichtlich und verständlicher wird:
# jeweils ein Repraesentant von mehrfach vorhandenen Dateien finden
md5deep -r SUCHVERZEICHNISS | sort -k1,33 | uniq -d -w32 > /tmp/doppelte_dateien
# hier nochmal sort, damit alle gleichen Dateien jeweils untereinander stehen
md5deep -r -M /tmp/doppelte_dateien SUCHVERZEICHNISS | sort -k1,33
# brauchst Du ja nicht mehr
rm /tmp/doppelte_dateien Löschen: ungünstig, ich weiß ja nicht, welche Du nun behalten willst. Performance: hmmm, geht so *g* Liese sich bestimmt noch optimieren
|
JayKay
(Themenstarter)
Anmeldungsdatum: 22. Oktober 2005
Beiträge: 111
Wohnort: Lampertheim
|
vielen vielen Dank reicht vollkommen aus ☺ hach, linux ist doch einfach .. geil 😉
|
Sid_Burn
Anmeldungsdatum: 23. Oktober 2004
Beiträge: 2159
|
Performance: hmmm, geht so *g* Liese sich bestimmt noch optimieren
Ja, indem man erstmal alle Dateiegrößen aller Dateien sammelst. Danach pickst man die Dateien heraus dessen Dateigrößen mehr als 1 mal vorkommt. Über diese Dateien lässt man dann die Hash Funktion laufen. Kommt ein Hashkey mehr als 2 mal vor, gibt man die identischen Dateien aus. \––\––\––\––\–– Ich habe das ganze, wie sonst immer, in Perl gelöst. Man muss das untenstehende Skript einfach in eine Datei Speichern (z.B. md5check) und ausführbar machen. Danach kann man das Programm entweder mit oder ohne Parameter aufrufen. Ohne Parameter, also nur "./md5check", scannt dann den aktuellen Ordner Inklusive Unterordner. Ansonsten kannst du auch einfach beliebige Ordner angeben die du durchscannen möchtest. md5check /mnt/daten /mnt/mp3 Würde also die beiden Ordner + Unterordner durchscannen. Performance war bei mir das ich ca. 1 Minute auf 80GB Daten brauchte um gleiche Dateien zu finden. (Bin echt erstaunt wieviele Doppelte Dateien ich habe... Muss ich selber mal aufräumen). Alleine das Hashen mit md5deep der selben Daten hat schon 35 Minuten und 46 Sekunden gedauert (Hab die Zeit gemessen *hust* 😉). Aber je nachdem welche Dateien man hat und vor allem wieviele große und auch identische umso länger dauert natürlich auch das Perl Skript, schneller als die Brute Force Methode, die einfach alles hasht, sollte es aber immer sein. Das Programm gibt dann letztendlich als erstes die MD5 Summe aus, und dadrunter dann mit Tabs eingerückt die Dateien die alle diese Hashsumme besitzen. Also dann auch identisch sind. Perl - Jäger der Verlorenen Clone Files
#!/usr/bin/perl
use warnings;
use strict;
use File::Find;
use Digest::MD5;
$ARGV[0] = '.' unless @ARGV;
my %files;
find( \&wanted, @ARGV );
sub wanted {
return if not -f $_;
my $size = -s $_;
my $filename = $File::Find::name;
push @{ $files{"$size"} }, $filename;
}
my %md5s;
while( my($size, $files_ref) = each %files ) {
if ( @$files_ref > 1 ) {
for ( @$files_ref ) {
if ( open FH, "<", $_ ) {
binmode FH;
push @{ $md5s{Digest::MD5->new->addfile(*FH)->hexdigest} } , $_;
close FH;
}
else {
warn "Cannot open $_: $!\n";
}
}
}
}
while( my($md5sum, $files_ref) = each %md5s ) {
if ( @$files_ref > 1 ) {
print $md5sum, "\n",
map( "\t$_\n", @$files_ref ),
"\n";
}
}
|
Doc_Fisher
Anmeldungsdatum: 21. Juli 2006
Beiträge: 104
Wohnort: Berlin
|
Ein feines Skript, vielen Dank!
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4577
Wohnort: Berlin
|
Wenn man die Hash-Werte nicht speichert um sie später wieder zu verwenden bringen die übrigens nicht unbedingt einen Geschwindigkeitsvorteil. Man muss bei gleichem Hash ja trotzdem nochmal die Dateiinhalte vergleichen um sicher zu gehen das sie wirklich gleich sind.
|
Sid_Burn
Anmeldungsdatum: 23. Oktober 2004
Beiträge: 2159
|
Marc 'BlackJack' Rintsch hat geschrieben: Wenn man die Hash-Werte nicht speichert um sie später wieder zu verwenden bringen die übrigens nicht unbedingt einen Geschwindigkeitsvorteil. Man muss bei gleichem Hash ja trotzdem nochmal die Dateinhalte vergleichen um sicher zu gehen das sie wirklich gleich sind.
Meinst du wegen meinen Skript? Also die MD5 Hashes werden schon gespeichert. Allerdiengs wird der MD5 Hash nur dazu genutzt um in einem Hash als Key zu fungieren, so das einfach alle Dateien mit dem selben Hash gefunden werden. Der Performancevorteil liegt ansonsten nicht in der Speicherung des Hashes sondern das ich nur die Dateien Hashe, wenn sie auch die selbe Dateigröße haben. Eine Datei die 3MB groß ist, kann nicht identisch sein zu einer Datei die 3,4MB Groß ist. Daher brauche ich da auch nichts Hashen (was ja letztendlich einmal die ganze Datei durchgeht). Alleine dieser Schritt bringt schon einen enormen Performance Vorteil. Ansonsten muss man eine Datei auch nicht komplett vergleichen. Es reicht solange die Datei durchzugehen bis veränderungen gefunden werden. Wenn man zwei 4 GByte dateien vergleicht, und sich das erste MB unterscheidet, dann muss ich nicht noch die restlichen 3,99 Gbyte durchgehen um zu entscheiden das sie nicht gleich sind. Von daher kann man das letzte implementieren, und nochmals Performanter sein. Das letzte habe ich allerdiengs nicht Implementiert, wollte ich aber mal machen... Bisher funktioniert das Skript folgendermaßen: 1) Alle Dateien finden mit gleicher Dateigröße. 2) Alle Dateien mit gleicher Dateigröße durchgehen, und MD5 Hash Generieren. 3) Dateien mit gleichen MD5 hash ausgeben. Wie ich das noch machen wollte. 1) Alle Dateien finden mit gleicher Dateigröße 2) Bei allen Dateien nur den ersten MB auslesen und Hashen. (Wenn der Hash für den ersten MB wie gesagt schon unterschiedlich ist, kann die Datei letztendlich nicht identisch sein) 3) Wenn Dateien aus schritt zwei noch übrig geblieben sind, dann diese jetzt komplett Hashen, oder solange die Dateien durchgehen bis differenzen gefunden werden. (Dateien durchgehen bis differenzen gefunden werden ist Performanter da nicht unbedingt die Datei komplett durchgegangen wird, sondern nur solange wie es reicht um festzustellen das sie nicht identisch sind. Allerdiengs können dann unter umständen viele Filehandles gleichzeitig geöffnet werden.) 4) Sofern identische Dateien aus schritt 3 übrig bleiben ⇒ Ausgeben.
|
Bierchen
Anmeldungsdatum: 1. Juli 2006
Beiträge: 81
|
Das Script ist der Hammer! Vielen Dank dafür! 😀 Nach zig-Migrationen meiner Daten von Rechner zu Rechner hat sich dermassen viel Müll angesammelt... mit ./md5check /home >/home/bierchen/dubletten.txt kam eine Datei mit 8 MB raus... 😲 Jetzt stellt sich die Frage: wie räumt man sowas auf, ohne die kommenden langen Winterabende komplett mit mc und F8 zu verbringen? Hat jemand eine Idee, wie man die Ausgabe sinnvoll weiterverarbeiten kann?
|
Sid_Burn
Anmeldungsdatum: 23. Oktober 2004
Beiträge: 2159
|
Anscheind sind bisher schon einige Personen über diesen Thread gestoßen. Habe mitlerweile schon des öfteren Anfragen bekommen ob ich auch eine Automatische Löschung einbauen werde. Habe mich mitlerweile mal an dieser Aufgabe gesetzt und das ganze nun realisiert. Das Ergebnis ist nun hier zu finden: http://ubuntuusers.de/paste/53236/ oder hier als direkter Datei Download: http://sidburn.de/pub/perl/find_duplicates Für die Funktionsweise müssen keine Perl Module nachinstalliert werden. Infos bekommt man wenn man das Programm mit dem Argument "--help" oder "--man" startet ("--man" gibt mehr aus). Anonsten das Programm einfach herunterladen. Als "find_duplicates" abspeichern und die Datei mit "chmod u+x" ausführbar machen. Soll das Programm für jeden Nutzer des Systems zur Verfügung stehen, so eigent sich dafür das Abspeichern in "/usr/local/bin/". Nicht vergessen: Hier am besten "chmod a+x /usr/local/bin/find_duplicates" eingeben. Wie werden Duplikate gefunden? 1) Von alle Dateien aus allen Verzeichnissen die angegeben werden. Werden die Dateigrößen ausgelesen. 2) Gibt es Dateien mit identischen Dateigrößen dann wird zuerst nur die ersten 64kb einer Datei eingelesen und für die ersten 64kb eine MD5 Summe generiert. 3) Hiernach wird geschaut ob es immer noch MD5 Summen gibt die mehrmals vorkommen. Wenn ja wird nun über die kompletten Dateien eine MD5 Summe generiert. 4) Wenn die Option "-d" angegeben wurde dann werden, bis auf eine, alle Dateien gelöscht. Ansonsten werden die identischen Dateien nur auf der Konsole ausgegeben. Warum Schritt 2) warum nicht gleich eine MD5 Summe über eine vollständige Datei generieren? Wegen der Performance. Haben wir zwei Daten die identisch groß sind, nämlich sagen wir mal 2 x 4GB dann müssten insgesamt 8GB von der Festplatte gelesen werden. Und zusätzlich dauert es auch etwas eine MD5 Summe zu Berechnen. Alleine für das Lesen würde man bei 60MB/sec knapp 2Min brauchen, ohne Berechnung der MD5 Summe. Sollten die Dateien aber bereits in den ersten 64kbyte nicht identisch sein. Dann macht es keinen Sinn noch die restlichen 3.99GB zu Lesen. Dadurch werden die Dateien auch nicht mehr identisch. Im Besten Fall müssen also nur 128 kbyte (2 * 64kbyte) gegenüber 8 Gbyte( 2 * 4 Gbyte ) eingelesen werden. Im Worst Case fall liest meine Methode dann 8 Gbyte + 128kbyte gegenüber 8 Gbyte ein. Macht dann kein großen Unterschied mehr. Allerdiengs bringt das ganze auch schon erhebliche Performance unterschiede bei kleineren Dateien. Bei 15.000 Musikdateien Durschnittsweise 3MB pro File müssten bei einem ganzen einlesen definitiv ca. 45GB von der Festplatte eingelesen werden. Im guten Fall liest diese vorgehensweise nur 937 MB ein (Wenn jede Datei mit jeder Dateigröße minimum zweimal vorkommt). Im besten Fall entsteht nur ein Overhead für die Dateigröße Abfrage und es wird nichts eingelesen und keine MD5 Summe generiert, wenn keine Dateigröße minimum zweimal vorkommt. Wenn im guten Fall 20% der Dateien Duplikate wären würde diese vorgehnsweise immer noch nur ca. 4GB gegenüber 45GB einlesen. (Und das auslesen bremst hier am meisten). Der Grund für den Zwischenschritt sollte nun klar ersichtlich sein. Wie präzise ist das Finden von Duplikaten? Da Dateien nicht direkt 1:1 verglichen werden sondern auf Basis Ihrer MD5 Summe, besteht immer eine Chance das zwei unterschiedliche Dateien mit der selben MD5 Summe existieren. Dies liegt in der Natur da man mit 128bit nur eine begrenzte Anzahl von unterschiedlichen Dateien abbilden kann. (340.282.366.920.938.463.463.374.607.431.768.211.456 um genau zu sein.) Allerdiengs wird nicht nur die MD5 Summe als Vergleich genommen sondern es muss auch die Dateigröße übereinstimmen. Die Chance das also zwei unterschiedliche Dateien als identische Dateien angesehen werden ist also schwinden gering. Aber für Theoretiker erreicht sie natürlich trotzdem nie 100% sondern nur 99.9999...% (ganz viele neuenen). Wenn dir daher das Automatische Löschen zu Risikoreich ist, dann nutze es nicht! Ich habe zwei identische Bilder, Video, ... die das Programm nicht gefunden hat? Das programm überprüft nur Dateigröße und letztendlich die Bytegenauigkeit (über den MD5 Hash). Wenn Beispielsweise ein Bild innerhalb eines Zeichenprogrammes mit "Speichern unter..." neu abgespeichert wurde, dann passiert in der Regel eine neue Kompression (wenn man beispielsweise JPEG auswählt) das Endresultat muss nicht identisch mit dem Original sein. Kann allerdiengs für den Betrachter identisch aussehen. Das gleiche kann auch für Textdateien gelten wo eine Datei in unterschiedliche Codierungen abgespeichert wird. Für den betrachter kann diese Datei dann allerdiengs trotzdem identisch aussehen. In der Regel sollten sich hierbei aber auch schon die Dateigrößen unterscheiden (Womit die Dateien nicht mehr identisch sind).
|
bodi
Anmeldungsdatum: 5. Oktober 2006
Beiträge: Zähle...
|
Hallo, ich habe das obere Skript einmal getestet. Es scheint super zu funktionieren Nun habe ich soviele doppelte Dateien, dass ich garnicht mehr alle im Terminal angezeigt bekomme. (Kann nicht genügend weit hochscrollen) kann man diese Ausgabe auch über eine Datei machen? Die dann z.B. auf dem Desktop liegt? Ich hätte noch ein paar nützliche Funktionen: - Größe der doppelten Datei in der Ausgabe anzeigen - Gesamtspeicherplatz der für alle mehrfach auftretende Dateien - Welche Datei wird eig. beim automatischen Löschen gelöscht? Wie wäre es mit einer Abfrage? wenn 3 gleiche Dateien gefunden werden, dass man dann 1, 2 oder 3 eingeben muss und dann die entsprechende Datei behalten wird Leider habe ich keine Ahnung wie man die oben genannten Funktionen in das Programm schustern kann, aber ich vermute, dass es wirklich nur Kleinigkeiten sind und würde mich sehr freuen, wenn das jemand vornehmen würde! MFG Bodi
|
Sid_Burn
Anmeldungsdatum: 23. Oktober 2004
Beiträge: 2159
|
Nun habe ich soviele doppelte Dateien, dass ich garnicht mehr alle im Terminal angezeigt bekomme. (Kann nicht genügend weit hochscrollen) kann man diese Ausgabe auch über eine Datei machen? Die dann z.B. auf dem Desktop liegt?
Du kannst die AUsgabe des Programmes einfach in eine Datei umleiten. find_duplicates /path/zu/ordner > output.txt
- Welche Datei wird eig. beim automatischen Löschen gelöscht? Wie wäre es mit einer Abfrage? wenn 3 gleiche Dateien gefunden werden, dass man dann 1, 2 oder 3 eingeben muss und dann die entsprechende Datei behalten wird
Die erste Datei im Array wird behalten. 😉 Das kann letztendlich eine beliebige sein. Die Manuelle Auswahl hatte ich mich auch überlegt wenn du aber 500 doppelte Dateien hast ist es eventuell auch nervig immer eine auszuwählen. Kann aber so eine Manuelle Auswahl sicherlich nochmal zusätzlich einbauen.
Ich hätte noch ein paar nützliche Funktionen: - Größe der doppelten Datei in der Ausgabe anzeigen - Gesamtspeicherplatz der für alle mehrfach auftretende Dateien
Kann ich auch noch alles einbauen. Werde ich wahrscheinlich noch. Ich habe Generell auch noch eine Weitere Vorstellung wie ich das mehr zu einem Richtigen Programm ausbaue und das da noch einige Funktionen hinzukommen. Allerdiengs wird das dann wohl etwas eigenständiges sein. Unabhängig von diesem Skript. Da ich das nicht so extrem aufblähen wollte. Dieses Skript soll auch nur mit reinen Core Perl Modulen Funktionieren. Das richtige Programm was ich plane wird damit nicht mehr auskommen. Allerdiengs weiß ich nicht wann ich damit anfange werde oder wann es fertig sein wird.
|
bodi
Anmeldungsdatum: 5. Oktober 2006
Beiträge: Zähle...
|
Hey danke für die schnelle Antwort! Danke für die Antwort mit dem Output in Datei. Wegen der Abfrage welche Datei gelöscht werden soll, wie wäre einfach eine weitere Option z.B. "-d -r" (delelete random) dass wäre dann das jetztige "-d" und ohne "-r" wäre es dann so wie unten beschrieben mit Auswahl. Denn selbst bei 500 Dateien wäre eine Auswahl welche gelöscht werden soll einfacher und schneller als alles von Hand über die Ausgabe zu suchen und zu löschen 😉 Wäre wirklich super nett, wenn du die Funktion reinmachen könntest, oder mir sagst wie man so was macht, leider kann ich das mit meinem Wissen nicht. Danke für deine Mühe! Bodi
|
klex
Anmeldungsdatum: 7. März 2008
Beiträge: 6
|
Sid Burn hat geschrieben:
Das Ergebnis ist nun hier zu finden: http://ubuntuusers.de/paste/53236/ oder hier als direkter Datei Download: http://sidburn.de/pub/perl/find_duplicates Für die Funktionsweise müssen keine Perl Module nachinstalliert werden.
Wenn ich das perl-skript ausführe bekomme ich diese Meldungen: perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LANG = "de_DE@euro" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C").
|
Sid_Burn
Anmeldungsdatum: 23. Oktober 2004
Beiträge: 2159
|
klex hat geschrieben: Sid Burn hat geschrieben:
Das Ergebnis ist nun hier zu finden: http://ubuntuusers.de/paste/53236/ oder hier als direkter Datei Download: http://sidburn.de/pub/perl/find_duplicates Für die Funktionsweise müssen keine Perl Module nachinstalliert werden.
Wenn ich das perl-skript ausführe bekomme ich diese Meldungen: perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LANG = "de_DE@euro" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C").
Dann ist dein System Fehlkonfiguriert. Die meldung sagt aus das deine Umgebungssprache nicht gesetzt ist, und er zur Sprache "C" (Damit ist nicht die Programmiersprache gemeint) zurückfällt. Die Meldung sagt dir auch welche Umgebungsvariablen du nicht gesetzt hast. LANGUAGE = (unset),
LC_ALL = (unset), Entweder setzt du mit "export LC_ALL="de_DE@euro" die Sprache. Aber das gilt nur für deine Aktuelle Shell. Du kannst die Sprache entweder auch in "/etc/profile" setzen oder zu /etc/environment. Vorhandene Sprachen siehst du auch mit "locale -a". Wenn du Debian (oder auch Ubuntu) nutzt kannst du auch "dpkg-reconfigure locales" eingeben und Sprachen auswählen und ein Default setzen. Wenn du kein Menü bekommst (und er nur die locales generiert) musst du eventuell erstmal mit "dpkg-reconfigure debconf" die Meldungsstuffe auf "Medium" setzen.
|
klex
Anmeldungsdatum: 7. März 2008
Beiträge: 6
|
Sid Burn hat geschrieben: Dann ist dein System Fehlkonfiguriert. Die meldung sagt aus das deine Umgebungssprache nicht gesetzt ist, und er zur Sprache "C" (Damit ist nicht die Programmiersprache gemeint) zurückfällt.
komisch, es ist eigentlich eine Standardinstallation Ubuntu 7.10, bei der Installation habe ich bereits Deutsch gewählt. Sid Burn hat geschrieben:
Wenn du Debian (oder auch Ubuntu) nutzt kannst du auch "dpkg-reconfigure locales" eingeben und Sprachen auswählen und ein Default setzen. Wenn du kein Menü bekommst (und er nur die locales generiert) musst du eventuell erstmal mit "dpkg-reconfigure debconf" die Meldungsstuffe auf "Medium" setzen.
Das alles reichte nicht ganz. Ich habe dann aufs Geratewohl aus diesem thread: http://forum.ubuntuusers.de/topic/1432/ einige Dateien editiert, reboot und das wars Danke
|