Moin, folgende Problematik: Ich habe eine Menge sehr schlampig archivierte Dateien mit einer bestimmten Endung quer verteilt auf einem riesigen Dateisystem. Erschwerend kommt hinzu, dass einige dieser Dateien in verschiedenen Verzeichnissen zwar den gleichen Namen haben (super Beispiel: "aktuell.bla" oder "test.bla"), aber einen unterschiedlichen Inhalt. Es gibt auf der anderen Seite auch jede Menge identische Dateien, die in verschiedenen Verzeichnissen abgelegt sind. Ich möchte alle diese Dateien nun gerne in EIN Verzeichnis kopieren, und zwar so, dass Dateien, die aus unterschiedlichen Verzeichnissen kommen, aber den gleichen Namen haben, sich nicht gegenseitig überschreiben. D.h., sie müssen einen anderen Namen bekommen oder ich muss die Verzeichnisstruktur mitkopieren (aber eben nicht andere Dateien, die sonst in diesem Verzeichnisbaum liegen.) Der resultierende Dateiname wäre erstmal fast egal, da ich den Originaldateiname aus dem Inhalt wiederherstellen kann. Dafür habe ich mir schon ein Script gebaut. Mein Ziel ist es, alle diese Dateien (ohne Duplikate und ohne Verlieren von verschiedenen Dateien mit gleichem Namen) in einem Verzeichnis zu haben. Bisher war mein Ansatz folgender: 1. Alle Dateien der Endung "bla" mit "find -iname *.bla >liste.txt" ausfindig machen und die Liste aller Dateien inkl. komplettem Pfad in eine Textdatei schreiben 2. Über ein Bash-Script die Datei einlesen und für jede einzelne Datei "cp" aufrufen, um diese in ein gemeines Verzeichnis zu kopieren. Hier entsteht natürlich die Überschreibe-Problematik. Wie löse ich das? 3. Mit "fdupes" die Duplikate löschen 3. Mit Hilfe meines Scriptes den Originaldateinamen wiederherstellen. Fertig. Wer kennt sich aus und kann mir bei Punkt 2 helfen? Schön wäre zum Beispiel eine Alternative zu "cp", die es schafft, den Pfad mitzukopieren. "cp" kann das zwar, aber nur mit der Option "-r", die dann alle anderen Dateien und Unterverzeichnisse mitkopiert.
Kleine Ideensammlung: Ich würde die Punkte (2) und (3) kombinieren. Wenn du in (1) schon die Liste der Dateinamen hast ("liste.txt"), kannst du mit $ cat liste.txt | xargs -d '\n' md5sum | sort -k 1 > md5sum.txt eine sortierte Liste von MD5-Prüfsummen mit dazugehörigen Dateinamen bekommen. Diese Liste müsstest du derart aufbereiten, dass mehrfach aufeinanderfolgende Zeilen mit gleicher Prüfsummenspalte ignoriert werden. Angenommen, die bereinigte Datei ist in "md5sum-uniq.txt", dann kannst du wieder mit einem kleinen Skript jede Zeile dieser Datei durchwandern und die angegebene Datei in dein Zielverzeichnis kopieren. Dabei würdest du die entsprechende Prüfsumme als Dateinamen verwenden. Ergebnis: Keine Kollisionen bei gleichem Dateinamen aber verschiedenem Inhalt, und jeder Dateiinhalt taucht nur einmal als Datei im Zielverzeichnis auf. Als letzten Schritt stellst du mit deinem existierenden Skript die Dateinamen aus dem Inhalt wieder her. Dabei wird natürlich angenommen, dass MD5 ein brauchbarer Hash für Dateiinhalte ist. Um die Wahrscheinlichkeit, dass zwei unterschiedliche Dateien als gleich erkannt werden (gleiche Prüfsumme) zu verringern, kannst du zusätzlich zu "md5sum" mit (bspw.) "sha1sum" eine zweite Liste erstellen, wahlweise auch mit anderen Hash-Verfahren. Im Zweifel kannst du ja beim Bereinigen der Liste darauf achten, welche Dateien übersprungen würden und diese manuell auf wirklich unterschiedlichen Inhalt prüfen. Sebastian. PS: Noch ein Tipp: Statt die Dateien zu kopieren (wenn du die Originale danach eh löschst), kannst du auch hard-links erzeugen (z.B. mit "cp -l" oder "ln"). Vorteil: Es geht deutlich schneller, da der Dateiinhalt nicht dupliziert werden muss, außerdem bestehen die Originale danach noch fort. Nachteil: Änderungen an den "Kopien" wirken sich auf die Originale aus und umgekehrt.
Robert schrieb: > 2. Über ein Bash-Script die Datei einlesen und für jede einzelne Datei > "cp" aufrufen, um diese in ein gemeines Verzeichnis zu kopieren. Hier > entsteht natürlich die Überschreibe-Problematik. Wie löse ich das? Entweder Du schaust zuvor nach, ob schon eine Datei vorhanden ist ("test -e ...") oder Du lässt cp die vorhandene Datei nicht überschreiben ("cp -n ..."). "$?" wird entsprechend gesetzt oder man macht es irgendwie so: "test -n dat1 dat2 || echo Fehlschlag".
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.