107. Dubletten (Duobletten) mit Batch finden
Einleitung
Das Finden von Datei-Duobletten bzw. Dateiduplikaten mit einer Batch
scheint zu einer der schweren Aufgaben zu gehören, da im Internet
bisher keine validen Auskünfte und der Verweis, dass Batches nicht zum Aufifinden von Dateiduplikaten
geeignet seien, selbst bei den etwas professionellen Seiten zur
Standardantwort gehören. Das ist eine mutige Aussage, wenn man bedenkt,
dass der Sternenhimmelstuermer gerade 14 Zeilen mit Grundbefehlen für diese Aufgabe
brauchte.
Der Sternenhimmelstuermer arbeitet wieder auf der Metaebene und zeigt
einen validen Lösungsweg, den jeder Batchschreiber nach Bedarf anpassen
kann - der Lösungsweg steht im Mittelpunkt und nicht die Batch per se.
Bereits in einer der letzten Abhandlung über die Bearbeitung von Tabellen lieferte
der Sternenhimmelstuermer den kompletten Befehlssatz in kleinen
Abwandlungen. Diese Abhandlung war eher für Anfänger gedacht, obwohl
das zusammenfügen von Tabellen nebeneinander in einem Dokument eine
bereits herausragende Leistung ist...
Der Sternenhimmelstuermer wird diesmal alles ein wenig kürzer erklären.
Wer nicht folgen kann, lese bitte die o. a. Abhandlung...
Batch
Dateiname:
doubletten.bat
Inhalt:
SET /p original=Geben Sie den Pfad zum Originalverzeichnis ein
SET /p vergleich=Geben Sie den Pfad zum Verzeichnis mit den Dubletten ein
set /p Dateiendung=Geben sie die Dateiendung ein
chcp 28591 > NUL
for %%i in ("%original%\*.%Dateiendung%") do @echo %%~ni ^:%%~zi ^:%%i >>org.log
chcp 28591 > NUL
for %%i in ("%vergleich%\*.%Dateiendung%") do @echo %%~ni ^:%%~zi ^:%%i >>verg.log
chcp 28591 > NUL
FOR /F "tokens=1,2,3* delims=:" %%i IN (org.log) DO echo %%i %%j %%k^:%%l >>ergebnis_%%j.log
chcp 28591 > NUL
FOR /F "tokens=1,2,3* delims=:" %%i IN (verg.log) DO echo %%i %%j %%k^:%%l >>ergebnis_%%j.log
for /f "delims=" %%a in ('dir /b /a-d ergebnis_*.log') do more +1 "%%a">neu_%%a
copy neu_*.log double.txt
del *.log
Die Erklärung der Batch in Schritten und eine Variante der Batch
mit zehn Zeilen für ein Verzeichnis mit Unterverzeichnissen kommen nach
Erklärung der Funktionsweise.
Für Profis ist die Abhandlung hier bereits beendet...
Funktionsweise der Batch mit einfachen Worten kurz erklärt:
Als erstes werden drei Eingaben erwartet:
1. Der Pfad zum Verzeichnis, wo die Originaldateien liegen
2. Der Pfad im Verzeichnis, mit dem die Dateien verglichen werden sollen
3. Die Dateiendung ohne Punkt: MP3, Doc, Docx, PDF, JPG - ist so ziemlich egal -
es sei denn es sind log
Logdateien oder txt
Textdateien
erster Arbeitsschritt
Dann geht es schon los! im ersten Arbeitsschritt werden die zwei
Verzeichnisse nach Dateien mit der eingegebenen Dateiendung
überprüft . Wird eine Datei gefunden, so wird der
Dateiname, die Dateigröße und der komplette Dateipfad in
eine Logdatei geschrieben. Es existieren dann zwei Logdateien (org.log - für die Dateien im
Verzeichnis mit den Originaldateien und verg.log für die Dateien
im Vergleichsverzeichnis).
zweiter Arbeitsschritt
Im nächsten Arbeitsschritt wird jede Zeile der beiden Dateien in ein
Dokument mit dem Namen ergebnis_%%j.log
übergeben. %%j ist in
diesem Fall die Dateigröße, die Bestandteil des ergebnis_%%j.log ist.
Dadurch, dass ein >>
doppelter Ausgabepfeil existiert, wird für jede Zeile eine einzelne
Logdatei geschaffen. Die Dateigröße wird übrigens in Bytes ausgegeben und
ist fast so individuell wie ein Hash-Wert...
Nach dem ersten For Befehl sind also vom org.log sämtliche Zeilen in
jeweils einer Datei mit dem Größenwert im Ergebnis.
Nach dem zweiten Durchgang des For - Befehls vom verg.log
kommen nun neue Ergebnis- Log-Dateien dazu, wenn Sie nicht
im Originalverzeichnis waren. Das ist unwichtig, aber zum Verständnis
absolut notwendig.
Der folgende Satz ist überwichtig zum
Verständnis: Durch den doppelten Ausgabepfeil wird bei einer
Dublette mit derselben Dateigröße die Ausgabe in die bereits
bestehende Datei des Ergebnis-Größe-Log als zweite
Zeile ergänzt. Da Dateiendung und Größe gleich sind, handelt es
sich mit an Sicherheit grenzender Wahrscheinlichkeit um eine
Dublette - insbesonder bei Dateien über 5 KB ist die
Wahrscheinlichkeit einer Verwechslung verschwindend gering...
Zwischenstand
Wir haben nun eine richtig große Anzahl mit Ergebnis-Größe-Log-Dateien
mit einer Zeile und je nach Anzahl der Dubletten auch
Ergebnis-Größe-Log-Dateien mit zwei oder mehr Zeilen, von denen wir mit
großer Sicherheit davon ausgehen können, dass es sich beim Inhalt der
Zeile um eine Dublette handelt (zur Erinnerung: in jeder Zeile stand
Dateiname, Größe und Dateipfad!
dritter Arbeitsschritt
Der nächste Arbeitsschritt ist ein wenig trickreich: Wir entfernen aus
jeder Ergebnis-Größe-Log-Datei die erste Zeile mit dem more Befehl.
Wozu ist das gut? Wir bekommen nun jede Menge "neu_%%a"- Dateien, wobei %%a
nur eine andere Version der Ergebnis-Größe-Log-Datei ist - nur
eben um die erste Zeile durch den More-Befehl reduziert.
Dadurch entstehen eine Menge Dateien, die
0 kb groß sind und somit eben auch keinen Inhalt haben (im wahrsten
Sinne Hüllen ohne Seele...). Aber unser Dublettendateien hatten ja
mindestens zwei Zeilen. Das ist das wichtige: Die zwei Zeilen werden
auf eine Zeile reduziert und
Hurra: wir haben das Zeil erreicht:
Dateien, in denen nur unsere Dubletten in einfacher Ausführung stehen!
In einer Zeile mit den drei Angaben Dateiname , Größe und Dateipfad.
vierter Arbeitsabschritt
Die Zeilen in den einzelnen Dateien müssen wir nur noch zusammenführen - der Sternenhimmelstuermer
bevorzugt hier einen einfachen copy
- Befehl: Mit der Anweisung allen Inhalt der Dateien neu_*.log
zusammenzufassen (in double.txt) werden alle Zeilen zusammengeführt. In
den Nullbyte Dateien ist kein Inhalt - also auch keine Zeile die
kopiert wird.
Im letzten Schritt werden die Log-Dateien mit del *.log zerstört. Hey, für
die Nullbyte-Dateien hätte man auch forfiles einsetzen können,
ein sinnentleertes Zwischenspiel für Batchschreiber, die gerne noch
eine Zeile mehr schreiben wollen.
Im double.txt steht
dann das Ergebnis, also sämtliche Zeilen mit übereinstimmender
Dateigröße und Endung. In der Zeile finden Sie Dateiname Dateigröße und
Dateipfad - alles durch Leerzeichen sauber getrennt.
Das Löschen der Dubletten können Sie dann selbstständig durchführen.
Mit der Vorlage double.txt echt
easy!
Die Batchschreiber, die diesen Weg nutzen werden, sind für die Löschroutine fit genug und Anfänger will
der Sternenhimmelstuermer nicht unglücklich machen, weil Sie wichtige
Dateien durch unbedarftes Handeln evtl. zerschießen. Hier ist der Sternenhimmelstuermer eigen -
es gibt genug Tools, die Dubletten finden, anzeigen und löschen.
Gleichwohl werden Fortgeschrittene diesen einfachen Lösungsweg schätzen.
Batch (Wiederholung des Codes)
Dateiname:
doubletten.bat
Inhalt:
SET /p original=Geben Sie den Pfad zum Originalverzeichnis ein
SET /p vergleich=Geben Sie den Pfad zum Verzeichnis mit den Dubletten ein
set /p Dateiendung=Geben sie die Dateiendung ein
chcp 28591 > NUL
for %%i in ("%original%\*.%Dateiendung%") do @echo %%~ni ^:%%~zi ^:%%i >>org.log
chcp 28591 > NUL
for %%i in ("%vergleich%\*.%Dateiendung%") do @echo %%~ni ^:%%~zi ^:%%i >>verg.log
chcp 28591 > NUL
FOR /F "tokens=1,2,3* delims=:" %%i IN (org.log) DO echo %%i %%j %%k^:%%l >>ergebnis_%%j.log
chcp 28591 > NUL
FOR /F "tokens=1,2,3* delims=:" %%i IN (verg.log) DO echo %%i %%j %%k^:%%l >>ergebnis_%%j.log
for /f "delims=" %%a in ('dir /b /a-d ergebnis_*.log') do more +1 "%%a">neu_%%a
copy neu_*.log double.txt
del *.log
Einfach blau-grünen Texbereich in eine Batch (*.bat) kopieren, in einem
beliebigen leeren Ordner platzieren
und mit Doppelklick starten: sämtliche relevanten und
erstellten Dateien für die Bearbeitung liegen relativ, also im
selben Ordner der Batch vor...Die Batch ist harmlos - nichts wird im
Wesen der Originale berührt...
Wer ein wenig wissen will, wie es so zwischenzeitlich läuft, sollte
einfach den Befehl del *.log löschen - dann können Sie sich die
ganzen Logdateien einmal in Ruhe anschauen - das hilft ungemein!
Erweiterungsmöglichkeiten in der Anwendung:
Tauschen Sie im ergebnis_%%j.log
durch ergebnis_%%i
in den zwei For-Befehlen aus, so wird die Prüfung über den Dateinamen
gemacht. Für den Sternenhimmelstuermer ist die Prüfung über die
Dateigröße wesentlich sicherer, da dort keine Leerzeichen, ü. ä oder ä
das Ergebnis ungünstig beeinflussen Können. Wie gesagt, bei zwei
Kriterien reicht die Dateigröße (andere Kriterium war Dateiendung - nur
mal so zur Erinnerung).
Eine andere Variante wäre es beim Vergleich ergebnis_%%i_%%j
zu verwenden, um nach Dateinamen und Größe die Dubletten zu
suchen...Dann müssen Sie die beiden For-Befehle und den kombinierten
For Dir-Befehl entsprechend anpassen. Das sind alles marginale
Veränderungen.
Trauen Sie dem Ergebnis nicht. Dann können Sie den Ergebnis.txt wieder
zerlegen und mit einem For Befehl mit findstr im ergebnis.txt gerne
einen Abgleich im orig.log starten...Die Batch kann beliebig aufgebläht
werden...
Sie können die Batch übrigens auf sieben Zeilen reduzieren: Einfach eine
Dateiliste von Verzeichnissen und Unterverzeichnissen mit Dateinamen
Größe und Dateipfad erstellen und ab dem For - Befehl ergebnis_%%j.log,
der dann nur einmal für die Liste verwendet wird, ist alles wieder
dasselbe. Wie das geht, wird noch im Abschnitt Variante der Suche in einem Verzeichnis mit Unterordnern erklärt.
Besonderheiten für Fortgeschrittene kurz und knapp
SET /p original=Geben Sie den
Pfad zum Originalverzeichnis ein
SET /p vergleich=Geben Sie den
Pfad zum Verzeichnis mit den Dubletten ein
set /p Dateiendung=Geben sie die
Dateiendung ein
Diese drei Zeilen mach nur die Eingaben der
User zu variablen, also nichts außergewöhnliches. Der Name der Variable
steht dann vor dem Gleichheitszeichen. Später muss dieser zwischen zwei
Prozentzeichen in einer Batch verwendet werden..
chcp 28591 > NUL
Dieser Befehl ist für ä,ü,ö usw zuständig -
ein typisch deutsches Problem. Die Batch funktioniert zwar auch ohne
diese Befehle - aber es kommen im Textdokument unleserliche Dokument
heraus, was auch für die Weiterbearbeitung nicht so günstig ist..
Der Befehl kommt vor jedem For-Befehl und wird deshalb in der kommenden Beschreibung mal unterschlagen...
for %%i in
("%original%\*.%Dateiendung%") do @echo %%~ni ^:%%~zi ^:%%i >>org.log
Im Pfad zum Originalverzeichnis %original%\
wird jede Datei *.
mit der %Dateiendung%
gesucht und von dieser wird (do) von einer gefundenen Datei
folgende Eigenschaften ausgegeben (@echo) : Dateiname mit
Endung (%%~ni ), danach
ein Doppelpunkt (^:),
danach die Dateigröße in Bytes ( %%~zi
), danach wieder ein Doppelpunkt (^:) der komplette Dateipfad
und am Ende der komplette Dateipfad (%%i ).
Wozu diese Doppelpunktarie?: Wir bauen uns eine kleine Tabelle mit
Doppelpunkten als Seperatoren! Das sind die Delims im übernächsten
For-Befehl, der gleich zm besseren Verständnis nochmal erklärt wird.
Einige aufgeweckte User müssten nun aufschreien: Das ist ganz schön
dumm, wenn man einen Doppelpunkt als Seperator benutzt, wo in einem
Dateipfad in der Regel immer ein Doppelpunkt steht - wie z. B. im Pfad
C:\blabla\pfad
Richtig - aber wenn man das weiß, kann man das auch korregieren:
FOR /F "tokens=1,2,3*
delims=:" %%i IN (org.log)
DO echo %%i %%j %%k^:%%l >>ergebnis_%%j.log
Der Sternenhimmelstuermer gibt hier 3 und Folgebestandteile als Tokens
ein und den Doppelpunkt als Seperator bzw. Delims in der For-Befehlssprache!
Der Knackpunkt des For - Befehls ist %%k^:%%l %%k ist dabei, was vor dem
Doppelpunkt steht, also z. B. das C bei C:\blabla\pfad
Danach wird wieder künstlich ein Doppelpunkt eingefügt. Dazu brauchen
wir wieder das Sonderzeichen ^
, weil sonst der Doppelpunkt nicht als Schriftzeichen interpretiert
wird.
Wir haben nun C: - mühsam nährt sich das Eichhörnchen.
Deshalb
brauchen wir %%l , welches dem Rest nach dem Doppelpunkt, also
\blabla\pfad entspricht und unmittelbar nach dem Doppelpunkt
eingefügt wird:
Der komplette Pfad ist also in dieser Zeile C:\blabla\pfad
Die Ganze Zeile wird dann in ergebnis_%%j.log
geschrieben. Bei einer Dublette stehen dann wieder zwei Zeilen in den
Ergebnis_Größe_Logs!
for /f "delims=" %%a in ('dir /b
/a-d ergebnis_*.log') do
more +1 "%%a">neu_%%a
Tja, hier werden dann sämtliche Dateien mit Namen
Ergebnis-Größe-log bearbeitet und die erste Zeile übersprungen und
der Rest ausgelesen und als %%a
alle Zeilen ausgegeben. Das Ganze in einem neu_%%a,
was dem Namen und der Dateiendung also neu_Größe.log entspricht.
Es gibt hier übrigens keine Delims in den Zeilen (also Separatoren),
was betont werden muss, damit immer ganze Zeilen gemeint sind.
Ist
wirklich ein wenig fies, da das nicht sofort verständlich ist.
copy neu_*.log double.txt
Alle (*) Dateien werden
nun in eine Datentextdokument kopiert. Wieso denn nun alle? Richtig,
die Null-Byte Dateien, bei durch Verwendung des more +1 entstanden sind
haben keinen Inhalt und beeinflussen damit auch nicht das Ergebnis...
del *.log
Am Ende werden sämtliche Logdateien mit dem Del-Befehl zerstört. Die
Nullbyte-Dateien natürlich auch - sind zwar Hüllen ohne Seele, nehmen
jedoch noch Cluster in Anspruch - eine etwas geschummelte Null (ist
aber irgendwo klar, denn allein der Dateiname hat ja einen gewissen
Speicherbedarf).
Variante der Suche in einem Verzeichnis mit Unterordnern
beliebigername.bat
SET /p verzeichnis=Geben Sie den Pfad zum verzeichnis ein
set /p Dateiendung=Geben sie die Dateiendung ein
chcp 28591 > NUL
for /f "delims=" %%i in ('dir %verzeichnis%\*.%Dateiendung% /s /b /a-d') do @echo %%~ni ^:%%~zi ^:%%i >>org.log
chcp 28591 > NUL
FOR /F "tokens=1,2,3* delims=:" %%i IN (org.log) DO echo %%i %%j %%k^:%%l >>ergebnis_%%j.log
chcp 28591 > NUL
for /f "delims=" %%a in ('dir /b /a-d ergebnis_*.log') do more +1 "%%a">neu_%%a
copy neu_*.log double.txt
del *.log
Dabei muss vor jedem For - Befehl die Anweisung zur Beibehaltung von ü,ö, ä eingegeben werden (chcp 28591 > NUL). Ein ziemlich deutsches Problem, daher mal wieder vergessen
Beim Einstieg dieser Batch muss ein DOS-Konformer Pfad gewählt werden!!!
Was heißt das? Bei der ersten Eingabe des Pfades zum Ordner oder dem
Laufwerk in der Hierarchie darf es keine Namen mit Leerzeichen im Pfad
geben. Außerdem nicht gegen die Regel mehr als sechs Buchstaben
verstoßen. Hintergrund: Beim Einstieg in den Dir Befehl sind wir durch
den For-Befehl im DOS-Modus. Aus z. B. dem Ordnernamen: Manfred
Sternenhimmelstuermer wird im DOS-Modus: Manfre~1
Hat die Batch den Einstieg gefunden, dann funktioniert der Rest auch.
Einige Nutzer geben Vornamen, Leerzeichen und Benutzername als
Benutzerkontonamen ein - der Sternenhimmelstuermer übrigens auch - um
sich immer daran zu erinnern Batches konform zu schreiben. Typische
Fehlermeldung: Der Pfad konnte nicht gefunden werden...Probieren Sie es
ruhig aus - wie gesagt: mehr als eine Fehlermeldung kann nicht
passieren...
Diese Batch bezieht sich auf die Suche in einem Verzeichnis mit
Unterordnern oder per se in einem ganzen Laufwerk. Hier wird nur eine
Dateiliste mit Namen Größe und Dateipfad gebildet. Der Rest ist so
ziemlich gleich. Die entscheidende Zeile zur Darstellung der eben
genannten Werte in Tabellenform in dem Textdokument wird nochmal
erklärt:
for /f "delims=" %%i in ('dir %verzeichnis%\*.%Dateiendung% /s /b /a-d') do @echo %%~ni ^:%%~zi ^:%%i >>org.log
Viele User können leider keine passenden Tabellen mit Angabe von
Name:Größe:Dateiname erstellen - insbesondere nicht von
Unterverzeichnissen.
Es bietet sich eine Hybridform mit Arbeitsteilung an: dir bis * ist der Pfad zu beliebigen Dateien - *.%Dateiendung% : * sind also die Dateien mit .%Dateiendung% . Zur Erinnerung %Dateiendung% ist die Variable für die Dateiendung, die der User am Anfang eingab: Also z. B. PDF
Ab /s beginnen die Parameter des Dir Befehls : /s - Unterordner werden durchsucht /b blanke Dateinamen abgefragt /a-d schauen Sie bitte in der cmd unter dir /? Returntaste in der Windowshilfe der CMD nach. Ab do @echo sind wir wieder bei anteilen der For-Schleife. %%i ist jeweils die vom dir-Befehl gefundene Datei mit der Dateiendung PDF in unserem Pseudobeispiel. Die Abfragetechnik %%~ni ^:%%~zi ^:%%i wurde bereits erklärt. In der Windowshilfe über for /? sind die übrigens auch nochmal dürftig erklärt.
Fazit
Die Sternenhimmelstuermerseite hat wieder als Meta-Seite bewiesen, dass
mit ein wenig Spieltrieb und Fantasie ein Lösungsweg zur Suche von
Dubletten möglich ist - alles mit Grundbefehlen, die in der Abhandlung über den Umgang mit
CSV-Dateien sehr ausführlich beschrieben wurden.
Damit ist das Thema Dubletten auch abgehakt. Es gibt genug Tools dafür
- es freut aber den Sternenhimmelstuermer in Abständen wider den
"Experten" zu beweisen, dass mit Batches alles möglich ist - und das
mit zehn Befehlszeilen... oder sogar in einer einfacheren Variation mit sieben Zeilen
Unumstritten hat die Sternenhimmelstuermer im Batchbereich mit die
progessivste Webseite mit veröffentlichten Batches eines Amateurs mit Erklärungen derselben.
Diese Abhandlungen könnten Sie interessieren:
Speicherfresserbatch Dokumente nach Größe suchen
Archivbatch Dokumente
nach Jahren in Ordner sortieren
Windowshilfe Windowshilfe
ausdrucken
switchbatch Zwischen
Registrywerten switchen
Lernbatch Eine selbst lernende
Batch
Bearbeitung von Tabellen eine Batch zum zusammenführen von Tabellen nebeneinander
Excel dasselbe: Die Projekte der Sternenhimmelstuermerseite sind
auf hohem Niveau:
Ernährungstabelle
Numerologie
Kalender
Verexexcelung von
Paragrafen
Anwesenheitslistenplan
Quartalsproblemlösung
genug Lesestoff und Probierstoff für Wochen und nur ein Bruchteil
dieser Seite insgesamt...