ubuntuusers.de

Dateinen finden, die nur auf der einen Festplatte vorkommen

Status: Gelöst | Ubuntu-Version: Kubuntu 14.04 (Trusty Tahr)
Antworten |

maplecut

Avatar von maplecut

Anmeldungsdatum:
7. Februar 2011

Beiträge: 239

Wohnort: Oberschwaben

Liebe Script-Experten,

mit FSlint kann ich doppelt vorhandene Dateien finden. Ich möchte aber die finden, die nur auf einer Externen Festplatte vorkommen.

Hintergrund: ich habe eine ältere Datensicherung und will wissen, ob es dort noch Dateien gibt, die ich /nicht/ auf meinem Arbeitsrechner habe, um zu prüfen, ob ich die noch benötige.

Vermutlich geht das am besten mit einem Shell-Script, weshalb ich es hier probiere.

Grüße, Maplecut

Benno-007

Anmeldungsdatum:
28. August 2007

Beiträge: 29240

Wohnort: Germany

Und wo ist jetzt die Frage? Dann gib halt deine externe Festplatte an...

maplecut

(Themenstarter)
Avatar von maplecut

Anmeldungsdatum:
7. Februar 2011

Beiträge: 239

Wohnort: Oberschwaben

FSlint zeigt mir die Duplikate. Das sind ca. 80.000. Ich möchte aber gerne wissen, ob auf der externen Platte welche sind, zu denen /kein/ Duplikat auf der internen Platte existiert. (Natürlich nicht die gesamten Platten, sondern jeweils unterhalb eines bestimmten Verzeichnises)

Also angenommen, intern gibt es die Dateien "a" "b" "c" "d" "e" "f" "g" und extern gibt es "c" "d" "e" "f" "g" "h" "i", dann sollte die Ausgabe lauten: "h" "i", denn diese beiden gibt es nur extern.

Oder formal: prüfe für jede externe Datei, ob für diese ein Duplikat intern existiert! Wenn ja: verwerfen!, wenn nein: ausgeben!

Habe ich was übersehen? Kann FSlint so was?

egi@lubuntu

Avatar von egi@lubuntu

Anmeldungsdatum:
25. November 2015

Beiträge: 71

Hallo maplecut,

quick and dirty würde ich folgendes probieren.

  1. Erzeuge eine Liste der Dateien, die auf Deiner externen Festplatte liegen. Wenn die Festplatte im Verzeichnis /media/extHD gemounted ist, geht das z.B. mit

1
2
cd /media/extHD
find . -print > /tmp/InhaltExtHD.txt
  1. mit folgendem kleinen Script suchst Du dann die Dateien:

1
2
3
4
5
6
7
#!/bin/bash

while read f; do
    if [ ! -e "${f}" ]; then
        echo "${f} is misssing!"
    fi
done < /tmp/InhaltExtHD.txt

Das geht auch alles in einer Zeile ohne Zwischendatei, aber so ist es nachvollziehbarer.

NB:

  1. Das Script muss in dem Verzeichnis aufgerufen werden, in dem die zu suchenden Dateien liegen sollen, damit die Pfadnamen passen.

  2. Das ganze setzt voraus, dass die Verzeichnis-Struktur gleich geblieben ist. D.h. eine Datei, die im Backup im Verzeichnis dir1 liegt wird als 'missing' angezeigt, auch wenn sie im Verzeichnis dir2 zu finden wäre.

Gruß egi

toni52

Anmeldungsdatum:
4. März 2015

Beiträge: 664

Hallo,

unter KDE sollten Komparator4 oder Krusader das können.

mfg

maplecut

(Themenstarter)
Avatar von maplecut

Anmeldungsdatum:
7. Februar 2011

Beiträge: 239

Wohnort: Oberschwaben

Danke, das verstehe ich soweit.

Leider sind aber die Verzeichnis-Strukturen nicht durchgehend gleich. Kann man die Pfade eliminieren, so dass nur noch die Dateinamen verglichen werden?

egi@lubuntu

Avatar von egi@lubuntu

Anmeldungsdatum:
25. November 2015

Beiträge: 71

Hallo maplecut,

wenn Du damit leben kannst, dass Dateien, die gleich heißen, nicht unterschieden werden, kannst Du wie folgt vorgehen.

  1. Erstelle eine Liste der Dateien auf der externen HD (Aufruf aus dem Verzeichnis, in dem die HD gemounted ist):

1
find . -type f -print | while read f; do echo "${f##*/}";done > /tmp/InhaltExtHD.txt
  1. Erstelle eine Liste Deiner aktuellen Daten (Aufruf aus dem Verzeichnis, in dem die Dateien liegen):

1
find . -type f -print | while read f; do echo "${f##*/}";done > /tmp/AktuelleDateien.txt
  1. Starte den Vergleich:

1
while read f; do if [ $(grep -FL "${f}" /tmp/AktuelleDateien.txt) ]; then echo "${f} is missing."; fi; done < /tmp/InhaltExtHD.txt

Gruß egi

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Normalerweise würde ich für sowas ja an rsync denken, denn das ist im Prinzip für sowas gemacht.

Auf jeden Fall kennt es die Optionen "--dry-run" (nur Simulation, mit "--verbose") und "--from0", so dass Du mit einer Null-terminierten Liste (z.B. aus find ... -print0) vergleichen kannst.
Was ich noch nicht gefunden habe, ist wie man dem die Verwendung der nackten Dateinamen beibringt. Das müsstest Du mal selber gucken ...

Ansonsten, wenn es wirklich "zu Fuß" sein muss, wäre es wahrscheinlich sinnvoll, die Dateienliste auf der internen Festplatte in ein Array einzulesen und dann beim Abgrasen der externen Festplatte zu gucken, was Du schon hast.

Problematisch bleibt dabei allerdings, dass Dir nicht kaputte oder falsche Dateien mit dem richtigen Namen als "korrekt" durchgehen. Das prüft rsync normalerweise nämlich auch, aber wenn Du selber vergleichst, dann musst Du sinnigerweise auch dafür selber Vorkehrungen treffen.

Grundsätzlich solltest Du bei Selbstgeschriebenem immer mit Null-terminierten Strings arbeiten, damit Dir nicht mal ein Leer- oder Sonderzeichen Deinen Kram zerschießt.

LG,

track

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

egi@lubuntu schrieb:

  1. Erstelle eine Liste der Dateien auf der externen HD (Aufruf aus dem Verzeichnis, in dem die HD gemounted ist):

1
find . -type f -print | while read f; do echo "${f##*/}";done > /tmp/InhaltExtHD.txt
  1. Erstelle eine Liste Deiner aktuellen Daten (Aufruf aus dem Verzeichnis, in dem die Dateien liegen):

1
find . -type f -print | while read f; do echo "${f##*/}";done > /tmp/AktuelleDateien.txt

Das ist ganz schlecht so etwas mit -print und Leseschleife zu machen. Viel besser wäre

1
find . -type f -exec sh -c 'for f; do echo "${f##*/}"; done' -- {} +

Noch einfacher ist

1
find . -type f -exec basename {} \;
  1. Starte den Vergleich:

1
while read f; do if [ $(grep -FL "${f}" /tmp/AktuelleDateien.txt) ]; then echo "${f} is missing."; fi; done < /tmp/InhaltExtHD.txt

Dafür kann man einfacher (und bei sehr großer Anzahl an Dateien auch effizienter) sort und diff nehmen.

Ich schlage mal einen etwas anderen Vergleich vor, der auch noch die Dateigröße berücksichtigt. Damit sollte die Qualität des Vergleichs deutlich besser sein:

1
2
3
find /media/user/externe-platte -type f -execdir stat --printf '%s\t%N\n' {} + >| extern.txt
find Videos Music -type f -execdir stat --printf '%s\t%N\n' {} + >| intern.txt
diff -U3 <(sort -u intern.txt) <(sort -u extern.txt) | egrep '^\+'

Man kann natürlich noch andere Dinge nutzen, die stat ausgibt, z.B. das Modifikationsdatum. Das hängt davon ab, was sinnvoll ist.

Anstatt stat kann man auch sha256sum nehmen - das berücksichtigt dann sogar den Inhalt, ist aber natürlich etwas langsamer. Dann sieht das so aus:

1
2
3
find /media/user/externe-platte -type f -execdir sha256sum {} + >| extern.txt
find Videos Music -type f -execdir sha256sum {} + >| intern.txt
diff -U3 <(sort -u intern.txt) <(sort -u extern.txt) | egrep '^\+'

Der entscheidende Trick hier ist find mit "-execdir" zu kombinieren, damit die ausgegebenen Dateinamen ohne Pfade (bzw. immer mit demselben Präfix "./") ausgegeben werden.

maplecut

(Themenstarter)
Avatar von maplecut

Anmeldungsdatum:
7. Februar 2011

Beiträge: 239

Wohnort: Oberschwaben

Danke für die Vorschläge, die ich erst jetzt gesehen habe, weil ich seit gestern Nachmittag aus irgend einem Grund keine E-Mail-Benachrichtigungen mehr über die Antworten erhalten habe.

Habe inzwischen Komparator4 ausprobiert, der schon recht gut das macht, was ich mir vorgestellt habe. Trotzdem sind mir Skripte lieber und ich werde, auch aus reinem Interesse, damit experimentieren. Setze auf gelöst!

Vielen Dank für Eure Hilfe!

Antworten |