Batch Windows-Dateiensuche möglich?

pizza4ever schrieb:
von dem search.txt steht im Ursprungspost aber nichts
Der TE mußte sich selbst erst klarwerden, was genau erreicht werden soll - ist Teil des Prozesses :).

Batch ist halt 'durchschaubar' und hier ohne Abhängigkeiten. Einfach als CMD speichern und los geht's.

Ist weder unanständig noch schmutzig und erfüllt oft die Erfordernisse. Warum schwere Geschütze rausholen für ein einmaliges Problem?!
 
mae1cum77 schrieb:
Für eine einmalige Durchführung leider nur bedingt praktikabel.
Bedingt unter der Voraussetzung, dass man eine Sprache benutzt, die sowas auch von Haus aus vorsieht?

Bin jetzt mal zu 'ner ungefähren Python-Variante gekommen:
Python:
import os
import shutil


map = {}
with open("output.txt") as f1:
    for db_file in f1:
        # print(db_file)
        path, filename = os.path.split(db_file)
        target_folder = os.path.relpath(path, "/sdcard/WhatsApp")
        # print(target_folder)
        map[filename.rstrip()] = {"files": [], "folder": target_folder}

with open("search.txt") as f2:
    for backup_file in f2:
        map[os.path.basename(backup_file).rstrip()]["files"].append(backup_file.rstrip())


for filename_entry in map:
    target = os.path.join(map[filename_entry]["folder"], filename_entry)
    count = 0
    for source in map[filename_entry]["files"]:
        if count == 0:
            # print(target)
            pass
        else:
            # print(target + "_" + str(count))
            target = target + "_" + str(count)
        count += 1
        shutil.copy(source, target)
    pass

Edit: Ist auch "dirty" (manche werden bspw. fragen, warum ich open() und rsplit() verwendet habe statt einfach readlines - es ist, weil es mir grade nicht eingefallen ist) aber müsste in etwa funktionieren bzw. zeigt das Prinzip.

Edit2:
Mir ist noch aufgefallen, dass shutil.copy die Verzeichnisstruktur zum Ziel nicht anlegt, wenn sie noch nicht existiert. Außerdem habe ich als Ziel statt relativ zum Arbeitsverzeichnis nun "E:\gefunden" eingestellt. Daher:
Python:
import os
import shutil

map = {}
target_root = os.path.abspath("E:/gefunden")
with open("scratch/output.txt") as f1:
    for db_file in f1:
        # print(db_file)
        path, filename = os.path.split(db_file)
        target_folder = os.path.relpath(path, "/sdcard/WhatsApp")
        target_folder = (os.path.join(target_root, target_folder))
        # print(target_folder)
        map[filename.rstrip()] = {"files": [], "folder": target_folder}
with open("scratch/search.txt") as f2:
    for backup_file in f2:
        map[os.path.basename(backup_file).rstrip()]["files"].append(backup_file.rstrip())

for filename_entry in map:
    target = os.path.join(map[filename_entry]["folder"], filename_entry)
    count = 0
    for source in map[filename_entry]["files"]:
        if count == 0:
            # print(target)
            pass
        else:
            # print(target + "_" + str(count))
            target = target + "_" + str(count)
        count += 1
        os.makedirs(os.path.dirname(source), exist_ok=True)
        shutil.copy(source, target)
        # print(source + " -> " + target)
    pass
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Marvolo und s1ave77
simpsonsfan schrieb:
Läuft halt im Gegensatz zu CMD und PS nicht einfach mal so. Ansonsten ist Python für solche Tasks top :).

Sollte halt getestet werden.
 
  • Gefällt mir
Reaktionen: simpsonsfan
mae1cum77 schrieb:
Läuft halt im Gegensatz zu CMD und PS nicht einfach mal so.
Stimme ich dir zu. Oder wenn man im anderen Extrem zwanzig verschiedene Python-Interpreter auf dem System rumliegen hat und sich in Dependencies verirrt. Außerdem mag ich bei Python nicht, dass Whitespaces (also die Einrückung) Teil der Syntax ist (obwohl sauber eingerückter Code natürlich sehr wünschenswert ist), aber mittlerweile bin ich Python halt gewohnt und man nimmt eigentlich immer das, was einem am vertrautesten ist.
 
  • Gefällt mir
Reaktionen: s1ave77
Python (und auch GIT & SQL Editor) habe ich alleine schon aufgrund der Editierung der WhatsApp Datenbanken (die Teil des ganzen Medien-Projekts hier sind - bzw. die Medien sind viel eher das letzte noch fehlende Puzzlestück bei dem großen Datenbankenprojekt) auf dem PC.

Sollte also kein großes Problem sein, das zum Laufen zu bekommen. Da ich mich aber WA-projekt-bedingt erst seit knapp 6 Wochen mit Coding, SQL und Programmieren überhaupt beschäftige, verstehe ich Vieles noch nicht. Am besten kenne ich mich mittlerweile mit der Sqlite-Sprache aus. Bei Python bräuchte ich ggf. dann noch ein paar Hilfestellungen, wie man den Code oben dann zum Laufen bringt. Einfach in eine Txt-Datei und als *py abspeichern, dann mit dem CMD hin navigieren und ausführen?

Kann ich aber erst morgen dann testen und ausprobieren.

Vielen Dank jedenfalls an alle, die sich hier bemühen!!
 
  • Gefällt mir
Reaktionen: s1ave77
Marvolo schrieb:
wie man den Code oben dann zum Laufen bringt. Einfach in eine Txt-Datei und als *py abspeichern, dann mit dem CMD hin navigieren und ausführen?
Zeile 30 (shutil.copy(source, target)) durch print(source + " " + target) ersetzen und, wie von dir erwähnt, in eine Datei mit Namen irgendwas.py in dem Ordner, in dem auch die beiden Dateien "output.txt" und "search.txt" liegen abspeichern, mit Powershell (oder eben cmd) in den Ordner navigieren und dann den Befehl python irgendwas.py ausführen. Das sollte dann (in die Konsole) eine Liste ausgeben, in der Quelldateien und Zieldateien mit vollem Pfad dastehen.
Oder den Befehl python irgendwas.py > Zuordnung.txt, um die Liste in einer Datei "Zuordnung.txt" zu haben.
oder print("copy " + source + " " + target) und python irgendwas.py > Zuordnung.bat, um eine .bat Datei zu haben, die dann kopieren kann.
Das Kopieren selbst dürfte (vermutlich) in python und in .bat gleich schnell oder langsam gehen.
 
  • Gefällt mir
Reaktionen: s1ave77
Jetzt muss ich nur nochmal fragen, wo in dem Python-Script jetzt Quell- und Zielordner angegeben werden müssen?

Ich habe /sdcard/WhatsApp im Script gefunden. Sollte das der Quellpfad sein?

Die eigentlichen Quell- und Zielpfade sind mittlerweile alle auf derselben externen Festplatte:

Quellpfad (Ordner, wo all die WA-Medien verstreut drin liegen): E:\MEDIEN\

Zielpfad (Ordner, wo dann die gefundenen Medien reinkopiert werden sollen): E:\gefunden\

Output.txt und Search.txt liegen, genauso wie die *py bzw. *batch-Datei alle auf dem Desktop nebeneinander.
Ergänzung ()

simpsonsfan schrieb:
Das Kopieren selbst dürfte (vermutlich) in python und in .bat gleich schnell oder langsam gehen.

Naja, aber dann wäre es ja kein wirklicher Gewinn zum derzeit schon vorhandenen Batch-Script, wenn sich zeitlich dadurch kein signifikanter Unterschied ergeben würde, oder?
 
Marvolo schrieb:
wenn sich zeitlich dadurch kein signifikanter Unterschied ergeben würd
Ich gehe davon aus, dass nicht das tatsächliche Kopieren in der jetzigen Batch so lange dauert, sondern das (potentiell 1000- oder millionenfache) Lesen der Textdatei wieder und wieder.
Der Teil fällt damit eben weg.

Ich gehe bei dem Skript von Folgendem aus:
  • in "output.txt" stehen Pfade wie "/sdcard/WhatsApp/Media/WhatsApp Images/IMG-20181229-WA00Ø.jpg"
  • in "search.txt" stehen Pfade wie "E:\MEDIEN\mich\nicht\interessierende\Verzeichnisstruktur\IMG-20181229-WA00Ø.jpg"
  • nachher soll "E:\MEDIEN\mich\nicht\interessierende\Verzeichnisstruktur\IMG-20181229-WA00Ø.jpg" nach "{AktuellesArbeitsverzeichnis}\Media\WhatsApp Images\IMG-20181229-WA00Ø.jpg" kopiert werden. Der Teil "sdcard\WhatsApp\" fällt also weg. Das meine ich, hattest du irgendwo mal geschrieben. Daher Zeile 10. Man kann statt relativ zum aktuellen Arbeitsverzeichnis auch einen anderen Pfad angeben. Aber sollte es ja nicht brauchen.
Nimm die Variante, bei der du Zeile 30 durch print("copy " + source + " " + target) ersetzt. Dann lass das einfach laufen und guck die Ausgabe an. In dem Fall kopiert es noch nichts, sondern erstellt nur die Zuordnungsliste, welche Datei wohin soll. Die kannst du dann angucken, ob die Einträge passen. und falls ja, kannst du tatsächlich kopieren.

Edit: Hab das Skript oben etwas angepasst.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: s1ave77
simpsonsfan schrieb:
  • nachher soll "E:\MEDIEN\mich\nicht\interessierende\Verzeichnisstruktur\IMG-20181229-WA00Ø.jpg" nach "{AktuellesArbeitsverzeichnis}\Media\WhatsApp Images\IMG-20181229-WA00Ø.jpg" kopiert werden. Der Teil "sdcard\WhatsApp\" fällt also weg. Das meine ich, hattest du irgendwo mal geschrieben. Daher Zeile 10. Man kann statt relativ zum aktuellen Arbeitsverzeichnis auch einen anderen Pfad angeben. Aber sollte es ja nicht brauchen.

Dieser Schritt ist zwar lieb gemeint, aber das tatsächliche Rüberkopieren zurück aufs Handy übernehme ich dann selbst / manuell, weil es da noch kleinere Dinge zu ändern/zu beachten gibt. Das muss nicht automatisiert erfolgen.

Die restliche Automation klingt so weit ich das gelesen habe richtig. Das heißt nun, der oben zitierte Eintrag muss nun auch aus dem Script entfernt werden? Lasse ich dieses Feld bei "/SDCARD/WhatsApp" dann einfach leer, oder muss die gesamte Zeile raus, oder wie genau muss es aussehen, dass da nicht direkt eine Fehlermeldung kommt?

PS:
1719062773344.png


Output.txt und search.txt liegen direkt neben media.py im selben Ordner.

Der Code, den ich verwendet habe:

Python:
import os
import shutil

map = {}
target_root = os.path.abspath("F:/gefunden")
with open("scratch/output.txt") as f1:
    for db_file in f1:
        # print(db_file)
        path, filename = os.path.split(db_file)
        target_folder = os.path.relpath(path, "/sdcard/WhatsApp")
        target_folder = (os.path.join(target_root, target_folder))
        # print(target_folder)
        map[filename.rstrip()] = {"files": [], "folder": target_folder}
with open("scratch/search.txt") as f2:
    for backup_file in f2:
        map[os.path.basename(backup_file).rstrip()]["files"].append(backup_file.rstrip())

for filename_entry in map:
    target = os.path.join(map[filename_entry]["folder"], filename_entry)
    count = 0
    for source in map[filename_entry]["files"]:
        if count == 0:
            # print(target)
            pass
        else:
            # print(target + "_" + str(count))
            target = target + "_" + str(count)
        count += 1
        os.makedirs(os.path.dirname(source), exist_ok=True)
        print("copy " + source + " " + target)
        # print(source + " -> " + target)
    pass
 
Zuletzt bearbeitet:
Marvolo schrieb:
Das heißt nun, der oben zitierte Eintrag muss nun auch aus dem Script entfernt werden? Lasse ich dieses Feld bei "/SDCARD/WhatsApp" dann einfach leer, oder muss die gesamte Zeile raus, oder wie genau muss es aussehen, dass da nicht direkt eine Fehlermeldung kommt?
Lass es einfach drin. Der Teil ist dann schlicht nicht in der Ordnerstruktur.
Und aus "scratch/search.txt" wieder "search.txt" machen. Das liegt nur daran, dass ich das bei mir in einem ohnehin geöffneten Repo teste und daher bei mir die zwei Dateien im Unterordner scratch liegen.

Am besten einfach mit viel print-statements testen, was rauskommt.
 
  • Gefällt mir
Reaktionen: Marvolo
1719069586302.png


Keine Ahnung, warum es nicht läuft...

Der neue Code nun:

Python:
import os
import shutil

map = {}
target_root = os.path.abspath("F:/gefunden")
with open("output.txt") as f1:
    for db_file in f1:
        # print(db_file)
        path, filename = os.path.split(db_file)
        target_folder = os.path.relpath(path, "/sdcard/WhatsApp")
        target_folder = (os.path.join(target_root, target_folder))
        # print(target_folder)
        map[filename.rstrip()] = {"files": [], "folder": target_folder}
with open("search.txt") as f2:
    for backup_file in f2:
        map[os.path.basename(backup_file).rstrip()]["files"].append(backup_file.rstrip())

for filename_entry in map:
    target = os.path.join(map[filename_entry]["folder"], filename_entry)
    count = 0
    for source in map[filename_entry]["files"]:
        if count == 0:
            # print(target)
            pass
        else:
            # print(target + "_" + str(count))
            target = target + "_" + str(count)
        count += 1
        os.makedirs(os.path.dirname(source), exist_ok=True)
        print("copy " + source + " " + target)
        # print(source + " -> " + target)
    pass
 
Liegt laut der Fehlermeldung am Encoding. Du kannst mal noch in Zeilen 7 und 15 for ... in F1.readlines() probieren.
Wahrscheinlich musst du die Textdateien und die Pythondatei in anderem Encoding abspeichern. Am besten einfach UTF-8 für alles. Und evtl. dem Python Script noch einen Encoding Hint geben.
 
So gut kenne ich mich damit leider nicht aus, um das nun völlig ohne Schritt-für-Schritt-Anleitung hinzubekommen. Zeilen 7 & 15 abändern in F1.readlines() kriege ich noch hin - das andere aber ohne exakte Schritt-für-Schritt-Anleitung leider nicht.
 
Die Fehlermeldung deutet darauf hin, dass Python die Datei mit Codepage 1252 einlesen will. Vermutlich ist die Datei aber mit UTF-8 enkodiert.

Du kannst mal probieren, die beiden open() Befehle so abzuändern:

Python:
open("output.txt", encoding="utf-8")
# bzw.
open("search.txt", encoding="utf-8")
 
  • Gefällt mir
Reaktionen: simpsonsfan und s1ave77
Hast du zufällig Notepad++ installiert? Die beiden Dateien (output.txt und search.txt) jeweils in Notepad++ aufmachen, im Menü "Kodiereung"->"Konvertiere zu UTF-8" (oder "Konvertiere zu UTF-8 ohne BOM", sollte egal sein, welches von beiden) drücken und dann speichern.

Grade eben habe ich deine output.txt aus #45 aufgemacht. Die enthält keine Sonderzeichen, d.h. da ist es egal. Die (aus dem Batchskript erzeugte) search.txt hat aber vermutlich Sonderzeichen und ist eben in Codepage 1252 kodiert, aber irgendwo passt was nicht.

Oder du kannst die Datei hier ebenfalls hochladen, dann können wir (ich) direkt testen. (Immer vorausgesetzt, dass in den Dateinamen keine sensiblen Informationen stehen, natürlich.)
 
  • Gefällt mir
Reaktionen: Marvolo
Es war wohl ein Problem mit dem ä in "März" und dem Encoding. Umwandeln in UTF-8 und explizite Angabe von UTF-8 bei open (wie @cx01 schreibt) haben geholfen.

8409 313 von den 9705 Dateien in output.txt sind genau 1x im Backup-Ordner (also in search.txt), 1296 Dateien wurden nicht gefunden , der Rest ist jeweils mehrfach vorhanden (und zwar in insgesamt 18206 Dopplungen - viel Spaß beim Durchschauen).

Ich hab zwei Batchskripte (dafür, nämlich Stapelverarbeitung, ist Batch auch konzipiert) angehängt, die hab ich nur als .txt hochgeladen, weil das Forum keine .bat erlaubt. Einfach umbenennen oder Inhalt in eine neue .bat-Datei kopieren.

Kannst ja die Kopierliste mal überfliegen. Sind aber halt 26 000 Zeilen.

Edit: Ich vermute, dass das deutlich schneller laufen sollte. Die Ordner zu erstellen hat bei mir im Test etwa 30s oder so gedauert. Eine Datei mit 26 000 Einträgen einmal durchzugehen bzw. 26 000 Befehle auszuführen geht halt schneller, als eine Datei mit 31 000 Einträgen 10 000 mal durchzugehen.
Das sind immerhin über 300 Millionen Textzeilen, die der Rechner da verarbeiten muss.
 

Anhänge

Zuletzt bearbeitet: (Edit2: Zahlen zu Dopplungen korrigiert)
  • Gefällt mir
Reaktionen: s1ave77
@simpsonsfan

Es läuft und kopiert - nur das mit den doppelten Dateien klappt nicht so ganz, wie es soll. Es nummeriert die doppelten Dateien nun NACH der Dateiendung, wodurch die Datei damit unbrauchbar wird, bzw. ich die dann alle erst händisch wieder in *jpg oder *mp4 umbenennen müsste:

1719166974654.png


Aber der Geschwindigkeitszuwachs beim Kopieren ist schon beachtlich.

Brauche ich das Python-Script nun überhaupt noch? Ich habe jetzt einfach diese Kopieren.bat-Datei gestartet, die ja anscheinend dasselbe macht wie das obige Python-Script?
 

Ähnliche Themen

Zurück
Oben