Kopieren von vielen einzelnen Dateien

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Tim533
User
Beiträge: 1
Registriert: Freitag 7. Februar 2020, 15:58

Hallo zusammen,

das folgende Problem bereitet mir seit Wochen Kopfzerbrechen:
Ich habe 2,7 mio. Bilddaten für die Erstellung einer künstlichen Intelligenz auf einer externen Festplatte (4Tb SSD) gesichert. Die Bilder sind zwischen 300 kb und 1,7 mb groß und befinden sich alle in einem Ordner. Um diese Daten vernünftig für die KI zu verarbeiten, müssen diese erstmal sortiert werden. Das Python-Skript hierfür ist bereits geschrieben, getestet und funktioniert wunderbar. Das ganze soll aber auf meiner lokalen Festplatte (NVMe Standard | M.2 | Samsung 970 EVO Plus | 2TB) gemacht werden da ich es auf der SSD bereits probiert habe und es ewig dauern würde. Also das Bottleneck ist auf jeden Fall die externe Festplatte.

Wie bekomme ich die einzelnen Dateien auf meine lokale Festplatte kopiert? Am liebsten würde ich es Stück für Stück machen. Also zB immer 100.000 Bilder. Hat jemand eine Idee wie ich das ganze mit Python machen könnte? Ihr seid meine letzte Hoffnung.

Viele Dank und viele Grüße, Tim
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du versuchst gerade rsync neu zu erfinden. Benutz einfach das.
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Rsync ist sicher eine gute und einfache Methode, um das noch etwas effizienter zu gestalten. Nur sollte man sich auch klar machen, dass es Grenzen gibt, wie weit man das optimieren kann. Ab einer bestimmten Größe dauert es halt und da gibt es dann nicht mehr so viel, was man noch tun kann, außer sich in Geduld zu üben.
Benutzeravatar
__blackjack__
User
Beiträge: 14051
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich würde rsync nicht mal unter dem Gesichtspunkt der Geschwindigkeit beim kopieren sehen, sondern dass das schon *fertig verfügbar* ist, statt das man da noch selbst etwas programmieren müsste. Wo man Fehler machen kann. Das es vielleicht marginal geringfügig schneller kopiert als eine Kopierschleife die in Python geschrieben ist, wäre für mich da nicht so entscheidend.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

__blackjack__ hat geschrieben: Freitag 7. Februar 2020, 22:28 Ich würde rsync nicht mal unter dem Gesichtspunkt der Geschwindigkeit beim kopieren sehen, sondern dass das schon *fertig verfügbar* ist, statt das man da noch selbst etwas programmieren müsste.
Wenn die Begründung wirklich ausschließlich ist, dass man es nicht selbst programmieren muss, verstehe ich nicht, weshalb die Empfehlung rsync und nicht und nicht einfach so etwas wie 'cp -Rua' (oder ein hoffentlich existentes Windows-Gegenstück) ist.
Zuletzt geändert von nezzcarth am Freitag 7. Februar 2020, 23:11, insgesamt 2-mal geändert.
Benutzeravatar
__blackjack__
User
Beiträge: 14051
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@nezzcarth: Gerade bei solchen Datenmengen würde ich ungern etwas nehmen wollen was man nicht abbrechen kann und dann ohne noch mal komplett von vorne anfangen zu müssen wieder anstossen kann.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Ja, das verstehe ich, und mache das ja auch so. Nur ist dann aber eben doch eine andere Begründung... ;) (Sorry für die Erbenzählerei... :/ Aber es sollte halt schon durchkommen, warum rsync hier die richtige Wahl ist, finde ich )
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es ist richtige Wahl weil es wie alles was der TE programmieren wollen würde nur kopiert was nicht schon kopiert wurde. Dein cp tut das nicht.
thomas38
User
Beiträge: 1
Registriert: Samstag 8. Februar 2020, 15:51
Wohnort: Köln

Hallo Tim,

von mir mal etwas Konkretes:

Voraussetzungen/Annahmen:
- Es sollen ca. 2,7 Mio Dateien von einer externen SSD-Festplatte vermutlich über USB2 oder USB3 (hoffentlich) angeschlossen auf die lokale SSD-Festplatte kopiert werden.
- Das Betriebssystem ist Windows10 oder Linux
- Der Kopiervorgang soll entweder nach einer bestimmten Anzahl zu kopierende Dateien oder durch ein anderes externen Ereignis beendet werden und beim erneuten Start nur fortgesetzt werden: bereits kopierte Dateien sollen nicht erneut kopiert werden.
- Auf der internen Festplatte ist noch genügend Platz für die Dateien vorhanden


Lösungsansätze:

Lösung A: Kopieren mit "Bordmitteln" des verwendeten Betriebssystems (Mit entsprechenden Optionen werden bereits bestehende Dateien nicht erneut kopiert):
Windows10: robocopy (ist bereits nach einer Installation vorhanden)
Linux: rsync (ist bereits nach einer Installation vorhanden oder kann einfach nachinstalliert werden)

Vorteil: Kein weiteres Programm erforderlich
Nachteil: Diese Programme müssen manuell abgebrochen werden, wenn der Kopiervorgang "unterbrochen" werden soll.

Lösung B: Python Programm:
Vorteil: Kontrollierter Abbruch: Es werden pro Aufruf nur eine bestimmte Anzahl von Dateien kopiert oder es wird durch ein externes Ereignis ordentlich beendet
Nachteil: Es muss geschrieben werden ;-)

Ablauf des Programms:

Code: Alles auswählen

Wenn Stop-Datei vorhanden ist:
   Stop-Datei löschen
   # Die Existenz der Stop-Datei ist das externe Ereignis, welches das Kopierprogramm signalisiert, ordentlich zu beenden.
   # Zu Beginn des Programms wird diese Datei ggf gelöscht, da das Programm sonst gar nichts macht

Wenn Datei "copied_files.txt" mit bereits kopierten Dateinamen vorhanden ist:
    Datei "copied_files.txt" lesen und in dict "copied_files" speichern

Datei "copied_files.txt" schreibend zum Anhängen öffnen
# Dort werden die in diesem Aufruf erfolgreich kopierten Dateinamen angehängt

Über alle Dateien im Quellverzeichnis:
    Wenn die maximale Anzahl von zu kopierenden Dateien erreicht ist:
        Programmende
        
    Wenn Stop-Datei existiert:
        Programmende
        
    Wenn Dateiname nicht in dict "copied_files" vorhanden ist:
        kopiere Datei ins Zielverzeichnis
        # z.B. mit shutil.filecopy
        Wenn Kopiervorgang erfolgreich:
            Dateinamen dem dict "copied_files" hinzufügen
            Dateinamen an "copied_files.txt" anhängen            
            Anzahl der kopierten Dateien um 1 erhöhen
        
Benutzeravatar
__blackjack__
User
Beiträge: 14051
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@thomas38: Was enthält denn das Wörterbuch `copied_files`? Sicher dass das ein `dict` und kein `set` sein sollte‽ Die Textdatei wäre mir ja auch nicht robust genug. Dateinamen können schliesslich Zeilenendezeichen enthalten — wie geht man damit in einer Textdatei um? Das müsste also mindestens mal so etwas wie eine CSV-Datei sein, damit Zeilenenden in Namen vom Ende eines Namens unterschieden werden kann.

Weiteres Problem ist die Kodierung. Textdateien haben ja in der Regel *eine* Kodierung. Dateienamen unter Linux/Unix sind aber keine Zeichenketten, sondern Byteketten, das kann also Probleme geben die in einer Textdatei zu speichern.

Warum braucht man diese Datei/das Wörterbuch überhaupt? Man kann doch einfach testen ob die Zieldatei schon existiert und gleich gross ist.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
snafu
User
Beiträge: 6867
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

thomas38 hat geschrieben: Samstag 8. Februar 2020, 16:46 Lösung A: Kopieren mit "Bordmitteln" des verwendeten Betriebssystems (Mit entsprechenden Optionen werden bereits bestehende Dateien nicht erneut kopiert):
Windows10: robocopy (ist bereits nach einer Installation vorhanden)
Linux: rsync (ist bereits nach einer Installation vorhanden oder kann einfach nachinstalliert werden)

Vorteil: Kein weiteres Programm erforderlich
Nachteil: Diese Programme müssen manuell abgebrochen werden, wenn der Kopiervorgang "unterbrochen" werden soll.
Zum Nachteil: Stimmt, aber diese Tools merken ja beim erneuten Programmlauf, was bereits kopiert wurde bzw was aktuell ist. Und die manuelle Unterbrechung kriegst du innerhalb von Python auch hin, wenn du das Kommando über die Popen()-Schnittstelle (im subprocess-Modul) ausführst. Darauf kannst du bei späterem Bedarf die terminate()-Methode aufrufen, um das externe Programm zu beenden. Dies lässt sich natürlich auch mit einem entsprechenden Button innerhalb einer GUI verbinden, falls so etwas geplant ist.
Antworten