3. Win 10 power-archiver 2016

Einleitung

Eigentlich ist diese Abhandlung nicht nötig, weil es bereits unter Win 7 eine Batch zum kopieren von beliebigen Dateien gab. Es ist nur so ein Übungsspiel, an dem wieder eine Reihe von Befehlen erklärt werden können. Damit wird die alte Batch zur Archivierung abgelöst, die unter Win7, Win 8 und Win 10 natürlich weiterhin funktioniert.

Diese Datei besteht zu 100 % aus einer Batch und Sie müssen nur beachten, dass der Einstiegspfad keine Leerzeichen oder Sonderzeichen enthält:

c:\irgendein Ordner\lagederbatch ist also nicht erlaubt, Genauso nicht auf oberster ebene eines Laufwerks, also C:\archiv.bat funzt nicht. Ansonsten funktioniert alles.
Warum diese Ausnahmen? Mehrere Zeilen des Codes zerlegen einen Pfad und ein Befehl braucht einen validen Pfad, die sind bei diesen Ausnahmen nicht gegeben.
Die Batch bricht dann einfach ab, kommt nicht über die ersten Zeilen, also kein Problem...

Ach ja, die Unterordner dürfen wiederum natürlich auch doppelte Namen enthalten!! Genauso dürfen die zu kopierenden Dateien Leerzeichen, ü, ä,ö...und - enthalten: Der Powerarchiver hat einen hohen Wirkungsgrad...


Die Dateien werden in Jahreszahlen von 1990 bis 2016 gesammelt. Das ist pure Wilkür und sie können die Jahreszahlen natürlich ändern, ich habe das rot markiert. Die Dateien werden auch in der Namensgebung nicht geändert und sind lediglich Kopien: Es wird nichts verändert!

Für Anfänger heißt das: einfach Code kopieren, eine Textdatei erstellen, den blauen Code hereinkopieren, Batch mit Doppelklick starten, die Dateiendung wie MP3, Doc, PDF oder ? eingeben und dann werden die Dateien kopiert: In Ordnern mit Jahresnamen von 1990 an.

Die geläufigen Dateiendungen habe ich eben aufgeführt und wie gesagt: Jpg, mp4 oder docx...ist alles erlaubt und bitte nicht andere Zusätze wie den obligatorischen Punkt verwenden...

Für Amateuere erkläre ich dann Zeile für Zeile und das ist absoluter Luxus, um selbst zu lernen wie die CMD denkt. Meine Beschreibungen sind im Netz die ausführlichsten und dabei soll es bleiben: ich fing auch mal mit einem dir-Befehl an...

Die Anwendung ist wieder auf eigene Gefahr und eigenes Risiko -:)


Für Anfänger:

Zur Erstellung einer Batch (*.bat) brauchen Sie nur bordeigene Mittel (Texteditor)

1. Als Vorraussetzung müssen Sie sich bekannte Dateiendungen anzeigen lassen: In beliebigen Ordner Registerkarte Ansicht: Dort Häkchen entfernen bei: Dateinamenerweiterungen.

2. Nun auf dem Desktop oder in einem Ordner mit rechter Maustaste auf freie Fläche drücken und neu - Textdokument auswählen.

3. Neues Textdokment öffnen (linker Doppelmausklick) und den o. a. Code durch kopieren über die Zwischenablage einfügen

4. Danach schließen. Abfrage mit Speichern mit ja beantworten.

5. Danach beliebigen Namen für die Archiv.bat vergeben - nur die Endung .bat ist vorgeschrieben - z. B-  sortieren.bat, genial.bat...

Dann den u. a. Code kopieren:

set /p ende=Geben Sie die Dateiendung ohne Punkt ein!
set destination=%~dp0%

for /f "delims=" %%i in ('dir %destination%*.%ende% /s /b /a-d') do @echo %%i>>pfadliste.log
for /f "delims=" %%I in (pfadliste.log) do echo %%~sI>>pfad.txt
for /f "delims=" %%I in (pfadliste.log) do @echo %%~ntI>>datum.txt
for /f "delims= " %%i in (datum.txt) do echo %%i.>>ganzdate.txt
for /f "tokens=1,2,3,4 delims=." %%i in (ganzdate.txt) do echo %%k>>realdate.txt

FOR /F "tokens=*" %%A IN ('findstr /N .* "realdate.txt"') DO echo %%A^:>>tableone.log
FOR /F "tokens=*" %%A IN ('findstr /N .* "pfad.txt"') DO echo %%A^:>>tabletwo.log
FOR /F "tokens=1,* delims=:"  %%i  IN (tableone.log) DO echo %%j>tableone_%%i.log
FOR /F "tokens=1,* delims=:"  %%i  IN (tabletwo.log) DO echo %%j>tabletwo_%%i.log
set /a x=1
:further
for /f "delims=" %%a in (tableone_%x%.log) do for /f "delims=" %%i in (tabletwo_%x%.log) do echo %%i%%a>tablenew_%x%.log
set /a x=%x%+1
if exist *_%x%.log (goto further) else goto final
:final
set /a y=1
:last
for /f "TOKENS=*" %%a in ('dir tablenew_%y%.log /b') do type "%%a">>result.txt
set /a y=%y%+1
if exist tablenew_%y%.log (goto last) else goto nowend
:nowend
FOR /F "tokens=1,2,3 delims=:"  %%i  IN (result.txt) DO echo "%%i:%%j";%%k>>resulttwo.txt
del *.log

for /f "tokens=1,2 delims=;" %%i in (resulttwo.txt) do echo %%i>>%%j.log
set /a w=1989
:nchml
if %w% GTR 2017 goto zuende
set /a w=%w%+1
if exist %w%*.log (copy %w%*.log %w%.bak) else goto nchml
goto nchml
:zuende

dir *.bak /b >logliste.txt
for /f "tokens=1,2 delims=." %%i in (logliste.txt) do md %%i
set /a x=1989
:anfang
if %x% GTR 2017 goto ende
set /a x=%x%+1
if exist %x%.bak (goto weiter) Else goto anfang
:weiter
SET ziel=%destination%\%x%
FOR /F "usebackq delims=" %%a in (%x%.bak) DO COPY %%a "%ziel%\*.*"
goto anfang
:ende
del *.log
del test.html
del test.txt
del datum.txt
del ganzdate.txt
del pfad.txt
del realdate.txt
del result.txt
del resulttwo.txt 
del logliste.txt
del *.bak


Die Batch sollte dann im obersten Verzeichnis liegen, da alle Dateien mit der gesuchten Dateiendung in relativer Lage zur Batch im selben Ordner und die Unterordner abgesucht und kopiert werden.

Danach wie gesagt Doppelklick auf die Batch. Dann die Dateiendung eingeben, die kopiert werden soll, so bald sich das Kommandozeilenfenster öffnet.

Es kann nichts passieren, da nur kopiert wird. Vorsicht, Log-Dateien im selben Verzeichnis der Batch und *.bak werden zerstört. Die Lage der Batch sollte dann der oberste Ordner sein, wo man kopieren will: alle Dateien im selben Verzeichnis und sämtlichen Ordnern in den Unterverzeichnissen (Ordnern) mit derselben Dateiendung werden nun kopiert  in  Unterordner mit der Jahresbezeichnung: Der Dateiname der Kopie entspricht dem Original.


Damit verlasse ich die Anfängerebene und ab jetzt geht es für Amateure weiter und ich beschreibe erstamal auf der Metaebene das Ziel:

Ich habe im Prinzip grundlegend versucht eine Dateiliste zu erschaffen, wo in einer Zeile der Pfad und die Jahreszahl drinsteht. Diese Liste exportiere ich dann in so viele Listen, wie es Dateien aus einem bestimmten Jahr gibt.

Dann schaffe ich so viele Ordner mit denselben Namen von Jahreslisten und kopiere diePfade in den Listen in die Zeitordner mit dem Jahresnamen.

Das ganze sieht dann Zeile für Zeile beschrieben so aus:


set /p ende=Geben Sie die Dateiendung ohne Punkt ein!
set destination=%~dp0% 

Die ersten beiden Zeilen sind erstmal von fast derselben Machart: In der ersten Zeile generiere ich eine Abfrage für die Variable ende, womit ich dann die Dateiendung meine: Der Text nach dem Gleichheitszeichen wird dem User angezeigt - set /p ist dazu der Befehl.

Damit ist die Dateiendung in der Variable %ende% (bei Batsch immer zwei Prozentzeichen...)

Die zweite Zeile ist nur die Variable für den Standort (Dateipfad) der Batch. Da brauchen sie nichts einzugeben! Wir haben also die Dateiendung nach Eingabe durch den User und kennen dank der fest geschriebenen Wendung %~dp0% den Dateipfad zur Batch wie z. B. c:\irgendeinordner...

Die nächsten Zeilen sind jetzt für viele Batchschreiber ein Krampf, weil der for-Befehl für viele eine Hürde ist:

for /f "delims=" %%i in ('dir %destination%*.%ende% /s /b /a-d') do @echo %%i>>pfadliste.log
for /f "delims=" %%I in (pfadliste.log) do echo %%~sI>>pfad.txt
for /f "delims=" %%I in (pfadliste.log) do @echo %%~ntI>>datum.txt
for /f "delims= " %%i in (datum.txt) do echo %%i.>>ganzdate.txt
for /f "tokens=1,2,3,4 delims=." %%i in (ganzdate.txt) do echo %%k>>realdate.txt

Ich will erstmal ein Dokument generieren (pfadliste.log), welches sämtliche ('dir %destination%*.%ende% /s /b /a-d') mp3 Dateien z. B. beinhaltet, die in Pfaden unterhalb und neben der Batch liegen (('dir %destination%*.%ende% /s /b /a-d')) . Da stehen also sämtliche Pfade drin.

Wenn sie wollen ist das eine Liste ohne irgendwelche Seperatoren ("delims="), wo untereinander der komplette Pfad eingetragen wird, für jede Datei eine Zeile und diese Liste wird übergeben, Zeile für Zeile (do @echo %%i) und deshalb auch (>>), weil mit einer Ausgabe immer wieder in Pfadliste.log  destruktiv überschrieben wird.

Das ist doch jetzt toll und wozu müssen wir dann im zweiten for Befehl die Liste ((pfadliste.log)) noch einmal konvertieren (pfad.txt)?

Nun, %%~sI  bedeutet, dass die Pfade ein Stück konvertiert werden und das ist leider notwendig, weil ich nun einmal weiß, dass ich später Probleme mit Dateinamen bekomme, die nicht im Dos-Format vorliegen. Denn ich will jetzt einmal nur Textdokumente verwenden und später mit Jahreszahl kombinieren und kopieren - das geht nicht ohne Bereinigung. Früher machte ich das mit einer extra Batch..., dann ist es doch besser im Vorfeld Probleme zu lösen.

Deshalb sagt die zweite Reihe auch nur übersetzt: Nimm die untereinanderstehenden Dateipfade aus der Liste von pfadliste.log und erstelle ein neues Dokument pfad.txt

Damit sind wir schon bei der dritten for Zeile: for /f "delims=" %%I in (pfadliste.log) do @echo %%~ntI>>datum.txt

Richtig, das sieht durch das @echo erstmal anders aus, heißt aber nur, dass außer dem Dospfad eben noch die Angaben zu der Datei reflexiv ausgegeben werden, vielleicht einmal die Visualisierung, wie so eine Zeile in test.html aussieht: C:\Users\Snappy\Desktop\test\tet\SHKKSP~1.MP3   12.09.2015 10:59 SHKKSP~1  
Für diese dämliche Ausgabeform kann ich nichts, deshalb habe ich erstmal mehraufwand.

Jetzt müssten sie verstehen, warum eine vierte For Schleife nötig wird: for /f "delims= " %%i in (datum.txt) do echo %%i.>>ganzdate.txt
Ich will jetzt den Pfad mit Titel und das Datum 2015 selektieren.

C:\Users\Snappy\Desktop\test\tet\SHKKSP~1.MP3 . 12.09.2015. Richtig, da ist noch ein kleiner Trick bei: Ich gebe einen weiteren Punkt ein, damit ich durchgängig einen Punkt als Separator habe: Das ist für die nächste for-Schleife unabdingbar...

Das ist immer noch dämlich, weil ich nach Jahren sortieren will und deshalb gleich wieder eine for-Stapelverarbeitung:

for /f "tokens=1,2,3,4 delims=." %%i in (ganzdate.txt) do echo %%k>>realdate.txt

Also extrahiere ich nun das Datum allein in die Datei realdate, wodurch da eine 2015 im Beispiel entsteht und danach eine fast unsichtbare Beschränkung, die wie ein Leerzeichen aussieht, aber ein AD AO - Schalter ist und die man mit Batchmitteln nicht so ohne weiteres wegbekommt. Ist zum Kotzen und muss später ausgeglichen werden:

Indes fügt der folgende Code nur  das Datum und den Pfad wieder zusammen:

FOR /F "tokens=*" %%A IN ('findstr /N .* "realdate.txt"') DO echo %%A^:>>tableone.log
FOR /F "tokens=*" %%A IN ('findstr /N .* "pfad.txt"') DO echo %%A^:>>tabletwo.log
FOR /F "tokens=1,* delims=:"  %%i  IN (tableone.log) DO echo %%j>tableone_%%i.log
FOR /F "tokens=1,* delims=:"  %%i  IN (tabletwo.log) DO echo %%j>tabletwo_%%i.log
set /a x=1
:further
for /f "delims=" %%a in (tableone_%x%.log) do for /f "delims=" %%i in (tabletwo_%x%.log) do echo %%i%%a>tablenew_%x%.log
set /a x=%x%+1
if exist *_%x%.log (goto further) else goto final
:final
set /a y=1
:last
for /f "TOKENS=*" %%a in ('dir tablenew_%y%.log /b') do type "%%a">>result.txt
set /a y=%y%+1
if exist tablenew_%y%.log (goto last) else goto nowend
:nowend
FOR /F "tokens=1,2,3 delims=:"  %%i  IN (result.txt) DO echo "%%i:%%j";%%k>>resulttwo.txt
del *.log


Diese Code wurde von mir zur Zusammenführung von Tabellen beschrieben und deshalbt verweise ich auf die Abhandlung über CSV.

Im Dokument resulttwo.txt sieht dann die Datei auf eine Zeile in einem Beispiel reduziert so aus:

"C:\Users\Snappy\Desktop\test\2015\DUSTIN~1.MP3";2015

Wichtig: Im letzten For-Befehl wurden sämtliche Reihen auf diese Bauart getrimmt, da stehen nun gleichartige Zeilen mit verschiedenen Daten drin - je nachdem aus welchem Jahr diese Datei stammt.

Die nächste Einheit schafft Bak-Dokumente, die die Jahreszahl als Überschrift und den Dateipfad in Anführungszeichen beinhalten. Das ist eine reine Routine zur Fehlerbereinigung der CMD, die hinter dem Datum ein unsichtbares Steuerzeichen mit sich rumführt und deshalb mache ich an diesem Punk aus 2015 .log eine 2015.bak ohne unsichtbares steuerzeichen-:)


for /f "tokens=1,2 delims=;" %%i in (resulttwo.txt) do echo %%i>>%%j.log
set /a w=1989
:nchml
if %w% GTR 2017 goto zuende
set /a w=%w%+1
if exist %w%*.log (copy %w%*.log %w%.bak) else goto nchml
goto nchml
:zuende
 
Ich setze dazu eine Variable w auf 1989 und lasse diese bei jedem Schleifendurchgang mit einer 1 addieren und wenn die Zahl größer als 2017 ist ( if %w% GTR 2017 goto zuende), dann beendet sich die Schleife.

Jedes Jahr wird also geprüft, ob ein Dokument vorliegt (%w%*.log = z. B. 2015 .log) Liegt ein solches Dokument vor, dann kopiere ich dieses Mistleerzeichen heraus und schaffe ein (%w%.bak =2015.log) ein Bak-Dokument: Deshalb der * als Wildcard.

Dasselbe mit den Pfaden von MP3 Dateien aus dem Jahr 2013, 2014, eben den Pfad jeder Datei als Jahresdokument und damit ist die erste Hälfte der Arbiet erledigt.

dir *.bak /b >logliste.txt
for /f "tokens=1,2 delims=." %%i in (logliste.txt) do md %%i
set /a x=1989
:anfang
if %x% GTR 2017 goto ende
set /a x=%x%+1
if exist %x%.bak (goto weiter) Else goto anfang
:weiter
SET ziel=%destination%\%x%
FOR /F "usebackq delims=" %%a in (%x%.bak) DO COPY %%a "%ziel%\*.*"
goto anfang
:ende


Die Bak-Dokumente werdennamentlich in einem Loglisten-Dokument zusammen gefasst, um die dazugehörigen Ordner zu erstellen,
da steht also

2011.bak
2015.bak
usw. drin, wenn es in diesen Jahren ein zu kopierendes E lement gab. for /f "tokens=1,2 delims=." %%i in (logliste.txt) do md %%i erschafft dann beim o. a. Beispiel die Ordner 2011 und 2015, weil md eben der Befehl ist der auf %%i, also dann 2011 wäre und delim ist der Punkt.

Dann existieren also Ordner mit Jahreszahlen und die zugehörigen Bak-Doument, in denen  der zu kopierende Pfad in Anführungszeichen steht.

SET ziel=%destination%\%x%
FOR /F "usebackq delims=" %%a in (%x%.bak) DO COPY %%a "%ziel%\*.*"


 
Das ist nun die eigentliche Kopieraktion: Der Pfad zum Ziel wird über eine weitere Variable x geliefert, die wieder von 1990 bis 2018 durchläuft.
(Gibt es ein Bak), welches vorher geprüft wurde, dann gibt es zu 100 % auch den Ordner im Ziel)

Wichtig ist die Formel "usebackq delims=" , denn die bewirkt, dass ein Dateipfad in Anführungszeichen als solcher im For-Befehl interpretiert wird.
Vereinfecht gesagt: Es wird nur sonst die Hälfte vom Pfad angezeigt oder gar nichts. Auch das %%a in Anführungszeichen nach Copy ist tödlich.

Der Copy Befehl in For-Schleifen ist eine Herausforderung und auch Semiprofis werden diese Codezeile zu schätzen wissen...

Die zwei Sterne im For-Befehl sind wiederum nur Wildcards, damit die Datei beim richtigen Pfad ankommt: Das ist eine stabile Konstruktion, aber mit eine der schwersten Zeilen in dieser Batch: Wenn sie die unter dreiStunden so hinbekommen, dann sind sie cleverer als der Autor, der wirklich eine Menge Variationen versuchte.

Impressum