137. Die Lehre von der Erstellung des Dospfads
Einleitung
Zu Pfingsten also eine kleine Abhandlung in christlicher Tradition zum
besseren Verständnis für die bessere Interaktion zwischen
Betriebssystem und User.
Manchmal kommt man gerade beim Batchschreiben ohne Dos-Pfade schlecht
ans Ziel.
Der Sternenhimmelstuermer beschrieb mit einer Abhandlung bereits, wie
man mit zwei Zeilen Code ganze Listen von Dos-Pfaden von Verzeichnissen
generiert:
for /f "delims=" %%i
in ('dir c:\*.pdf /s /b /a-d') do
@echo %%i>>pfadliste.log
for /f "delims=" %%I in (pfadliste.log) do echo %%~sI >>dos.txt
(Die rote Pfadangabe können Sie durch ein beliebiges Verzeichnis ihrer
Wahl verändern, statt pdf können Sie jede beliebige Dateiendung oder
die Wildcard Stern: * setzen.
Wie üblich wurden diese zwei Zeilen im Netz weitestgehend ignoriert -
die Lobby des Sternenhimmelstuermes ist nicht groß...
Wie dem auch sei, die Ermittlung mit Batchmitteln und dem Babycode des
Sternenhimmelstuermers zur Umwandlung und bestimmung des Dospfades war
eine Herausforderung, die kein Batchschreiber bis ins Jahr 2013
wirklich löste - jedenfalls bietet niemand im Netz eine wirklich gute
Lösung an...
Der Sternenhimmelstuermer brauchte gerade für seine
Sprachverschlüsselungssoftware NoNSA einen validen Dos-Pfad und
die Lösung ist jetzt zu 95 % valide:
Schwächen: Zur Ermittlung der Kennzahl des Doscodes bei mehreren
Dateien mit identischen Dosnamen ermittelt der Sternenhimmelstuermer
über die Zahl der Buchstaben des Dateinamens die Identität der Datei:
ein direkter Vergleich von Buchstaben wäre valider, aber das kann jeder
ambitionierte Batchschreiber selbst abändern und das Spielkind
Sternenhimmelstuermer braucht diesen Code für eine andere Abhandlung
über KI, try und error, Missverständnisse und....
Bedienung und Quellcode
Als erstes den Code und dann wie imme eine Erklärung in groben Zügen -
Für viele Anfänger ist nach der Bedienung der Batch eh alles gesagt:
Sie brauchen zwei Dokumente:
Das eine muss change.txt heißen,
da schreiben oder kopieren Sie den vollständigen Pfad mit beliebigen
Dateinamen rein
Das zweite heißt irgendeinName.bat - richtig, Sie können den Namen der
Batch frei wählen
---
Einschub
Sie sollten auf ihrem Betriebssystem die Einstellung Erweiterungen bei bekannten
Dateitypen
ausblenden deaktivieren, damit Sie im folgendenen Schritt
Babel.txt in Babel.bat umbenennen können:
Beliebigen Ordner öffnen: Organisieren
-
Layout
- Menüleiste
auswählen. In der Menüleiste: Extras - Ordneroptionen
- Reiterkarte
Ansicht:
Dort Häkchen entfernen bei: Erweiterungen
bei bekannten
Dateitypen ausblenden.
Einschubende
---
Auf ihrem PC mussen zur Erstellung von dem Dokument ihrdospfad.txt VBS aktiviert
sein!
Ohne VBS geht gar nichts.
Dann muss die Datei in change.txt
auch wirklich auf ihrem PC existieren und der Dateipfad in
"Klarschrift" auch wirklich richtig geschrieben werden! Mit
Großschreibtaste und rechte Maustaste gleichzeitig können Sie bei einer
beliebigen Datei den Pfad kopieren (als Pfad kopieren im Kontextmenü).
Die Anführungszeichen können Sie da lassen, aber es geht auch ohne...
Der Pfad kann auf ein beliebiges Dokument oder eine Datei verweisen -
größe usw. ist egal. Einzige Einschränkung: Hat ein Verzeichnis bzw.
Ordner ein ä,ö oder ü im Namen, dann müssen Sie ihren eigenenen
Workaround schreiben-:)
Ordner heißt nicht Datei oder Dokument! Da können ä,ü, Leerzeichen oder
andere Gemeinheiten drin stehen - dafür ist der Dospfad ja auch
gedacht...
Mal ein Beispiel für einen erlaubten Pfad:
"C:\Users\Manfred
Sternenhimmelstuermer\Desktop\dos pfad\vers\probe schön - Kopie.pdf"
Mal für einen verbotenen Pfad:
"C:\Users\Manfred stürmer\Desktop\dos
pfad\vers\probe schön - Kopie.pdf"
Das ü im Dateipfad geht nicht auf Dos-Ebene, daher sollten Sie es
vermeiden ein Verzeichnis bzw. im Volksmund Ordner z. B. mit Ärger zu titulieren...
Quellcode:
change.txt mit vollständigen Pfad
erzeugen Sie!
irgendeinName.batist der Name der Batch
Quellcode:
for /f "delims=" %%I in (change.txt) do echo %%~dI%%~pI >>prepfad.txt
for /f "delims=" %%I in (prepfad.txt) do echo %%~sI >>dospfad.txt
for /f "delims=" %%I in (change.txt) do echo %%~xI >>dtendung.txt
for /f "delims=" %%I in (change.txt) do echo %%~nI >>predname.txt
set destination=%~dp0%
>"%destination%zhlprd.bat" ECHO @echo off
>>"%destination%zhlprd.bat" ECHO setlocal enabledelayedexpansion
>>"%destination%zhlprd.bat" ECHO set /p String=^<predname.txt
>>"%destination%zhlprd.bat" ECHO call :StrLength %%String%%
>>"%destination%zhlprd.bat" ECHO set /a StrLength=%%StrLength%% +4
>>"%destination%zhlprd.bat" ECHO echo %%StrLength%% ^>zprd.txt
>>"%destination%zhlprd.bat" ECHO exit
>>"%destination%zhlprd.bat" ECHO goto :eof
>>"%destination%zhlprd.bat" ECHO :StrLength
>>"%destination%zhlprd.bat" ECHO set tmpString=%%*
>>"%destination%zhlprd.bat" ECHO set Length=0
>>"%destination%zhlprd.bat" ECHO :StrLengthLoop
>>"%destination%zhlprd.bat" ECHO if not "!tmpString:~%%StrLength%%,1!"=="" (
>>"%destination%zhlprd.bat" ECHO set /a StrLength += 1
>>"%destination%zhlprd.bat" ECHO goto StrLengthLoop
>>"%destination%zhlprd.bat" ECHO )
>>"%destination%zhlprd.bat" ECHO goto :eof
>>"%destination%zhlprd.bat" ECHO :Ende
start /wait zhlprd.bat
del zhlprd.bat
for /f "delims=" %%I in (predname.txt) do echo %%I >>"%%I".tnt
for /f "delims=" %%i in ('dir *.tnt /b /a-d') do @echo %%i>>pfadliste.log
for /f "delims=" %%I in (pfadliste.log) do echo %%~sI >>dos.txt
for /f "delims=" %%I in (dos.txt) do echo %%~nI >>dosname.txt
timeout /t 1
for /f %%a in (dospfad.txt) do for /f %%i in (dosname.txt) do echo %%a%%i>>predospfd.txt
timeout /t 1
for /f %%a in (predospfd.txt) do for /f %%i in (dtendung.txt) do echo %%a%%i>>enddospfad.txt
:neu
set /a x=1
:newround
set /a x=%x%+1
set /a Y=%x%-1
set destination=%~dp0%
>"%destination%bereinigung.vbs" ECHO Set objFSO = CreateObject("Scripting.FileSystemObject")
>>"%destination%bereinigung.vbs" ECHO Set objFile = objFSO.OpenTextFile("%destination%dosname.txt", 1)
>>"%destination%bereinigung.vbs" ECHO strText = objFile.ReadAll
>>"%destination%bereinigung.vbs" ECHO objFile.Close
>>"%destination%bereinigung.vbs" ECHO strNewText = Replace(strText, "%y%", "%x%")
>>"%destination%bereinigung.vbs" ECHO Set objFile = objFSO.OpenTextFile("%destination%dosname.txt", 2)
>>"%destination%bereinigung.vbs" ECHO objFile.WriteLine strNewText
>>"%destination%bereinigung.vbs" ECHO objFile.Close
start /wait bereinigung.vbs
del bereinigung.vbs
timeout /t 1
for /f %%a in (dospfad.txt) do for /f %%i in (dosname.txt) do echo %%a%%i>>predospfd_%x%.txt
timeout /t 1
for /f %%a in (predospfd_%x%.txt) do for /f %%i in (dtendung.txt) do echo %%a%%i>>enddospfad_%x%.txt
set /p vgl=<enddospfad_%x%.txt
if exist %vgl% goto newround
del enddospfad_%x%.txt
set /a z=x-1
set /p ergebnis=<enddospfad.txt
if %z% equ 1 echo %ergebnis%>ergebnis.txt
if %z% equ 1 goto ausstieg
copy enddospfad_*.txt ergebnis.txt
timeout /t 1
echo %ergebnis% >>ergebnis.txt
:ausstieg
for /f "delims=" %%a in (ergebnis.txt) do dir /b %%a>>erg.txt
FOR /F "tokens=*" %%A IN ('findstr /N .* "erg.txt"') DO echo %%A: >>erg.log
FOR /F "tokens=*" %%A IN ('findstr /N .* "ergebnis.txt"') DO echo %%A: >>ergebnis.log
FOR /F "tokens=1,2,3,4* delims=:" %%i IN (ergebnis.log) DO echo %%j^:%%k%%l >>pfad_%%i.log
FOR /F "tokens=1,2,3,* delims=:" %%i IN (erg.log) DO echo %%j>>name_%%i.log
Set /a x=0
:searchloop
set /a x=%x%+1
if not exist name_%x%.log goto finale
set destination=%~dp0%
>"%destination%zhlprd%x%.bat" ECHO @echo off
>>"%destination%zhlprd%x%.bat" ECHO setlocal enabledelayedexpansion
>>"%destination%zhlprd%x%.bat" ECHO set /p String=^<name_%x%.log
>>"%destination%zhlprd%x%.bat" ECHO call :StrLength %%String%%
>>"%destination%zhlprd%x%.bat" ECHO set /a StrLength=%%StrLength%%
>>"%destination%zhlprd%x%.bat" ECHO echo %%StrLength%% ^>zprd%x%.txt
>>"%destination%zhlprd%x%.bat" ECHO exit
>>"%destination%zhlprd%x%.bat" ECHO goto :eof
>>"%destination%zhlprd%x%.bat" ECHO :StrLength
>>"%destination%zhlprd%x%.bat" ECHO set tmpString=%%*
>>"%destination%zhlprd%x%.bat" ECHO set Length=0
>>"%destination%zhlprd%x%.bat" ECHO :StrLengthLoop
>>"%destination%zhlprd%x%.bat" ECHO if not "!tmpString:~%%StrLength%%,1!"=="" (
>>"%destination%zhlprd%x%.bat" ECHO set /a StrLength += 1
>>"%destination%zhlprd%x%.bat" ECHO goto StrLengthLoop
>>"%destination%zhlprd%x%.bat" ECHO )
>>"%destination%zhlprd%x%.bat" ECHO goto :eof
>>"%destination%zhlprd%x%.bat" ECHO :Ende
start /wait zhlprd%x%.bat
set /p vgl=<zprd%x%.txt
set /a y=%vgl%
set /p orig=<zprd.txt
set /a z=%orig%
if %y% EQU %z% goto finale
goto searchloop
:finale
copy pfad_%x%.log ihrdospfad.txt
set /p oneproof=<ihrdospfad.txt
if exist %oneproof% goto daswars
for /f %%a in (dospfad.txt) do for /f %%i in (predname.txt) do echo %%a%%i>>norml.txt
for /f %%a in (norml.txt) do for /f %%i in (dtendung.txt) do echo %%a%%i>ihrdospfad.txt
:daswars
del *.tnt
del dos.txt
del dosname.txt
del dospfad.txt
del dtendung.txt
del enddospfad.txt
del enddospfad_*.txt
del erg.log
del erg.txt
del ergebnis.log
del ergebnis.txt
del name_*.log
del pfad_*.log
del predname.txt
del predospfd.txt
del predospfad.txt
del zhlprd*.bat
del zprd.txt
del zprd*.txt
del pfadliste.log
del prepfad.txt
del predospfd_*.txt
del norml.txt
---
Ein Wort über DOS-Pfade
Dateinamen
werden in der Regel auf ihrem Windows-Betriebssystem in einen Dospfad
aufgelöst. Das kann man unterdrücken, aber ist nicht zu empfehlen, da
selbst im Profilager auf die Kommandozeile manchmal zugegriffen wird.
Der Pfad mit Dateinamen: C:\Users\Manfred
Sternenhimmelstuermer\Desktop\dos pfad\vers\probe schön - Kopie.pdf
wird dann in C:\Users\MANFRE~1\Desktop\DOSPFA~1\vers\PROBES~2.pdf aufgelöst.
Der Sternenhimmelstuermer verwendet auf seinem Windows 7 immer einen
Doppelnamen als Benutzernamen mit der Folge, dass ein hoher Anteil von
Batches von den Semiprofis nicht funktioniert! a würden einige Profis
einen roten Kopf bekommen, wenn der Sternenhimmelstuermer mal
veröffentlichen würde, was so nicht funktioniert, aber so was tut man
ja nicht...
Egal, verwenden Sie als User keine Doppelnamen und bei Ordnern ist es
manchmal vernünftiger einen kurzen Namen zu vergeben.
Der Pfad da oben ist fies: Im Pfad ist nicht nur ein Doppelname,
sondern auch der Ordner dos pfad. Dieser ist aufgelöst in Dos: DOSPFA~1
Es gilt die Regel: 6 Buchstabe, ein Tildezeichen und eine Zahl
zur eindeutigen Identifizierung.
Wäre jetzt der Name DOSPFA~2 ,
dann würde ein zweiter Ordner mit Namen wie z. B. dos pfad ordner existieren.
Sie sehen das Problem: Der PC bekommt auf Dos-Ebene nur die Hälfte mit.
Diese bewußtseinseinschränkung führt zu lustigen Fehlern in der
Programmierwelt ist aber in den neueren Betriebssystemen nicht mehr
wirklich relevant - für Programmierer aber ein immer noch
aktuelles Problem, da Beispielsweise der Command-Befehl in Ihrer
Registry fester Bestandteil bei unzähligen Operationen ist. Der
Sternenhimmelstuermer ist bekannt daür, dass er DOS immer noch als
führende Sprache der alten Welt propagiert...
Beim Dateinamen dasselbe Spiel.
Um den Dosnamen einer Datei herauszufinden, gibt es bekanntlich den dir
/x - Befehl, der jedoch so unglücklich implementiert wurde und dermaßen
eingeschränkt verwendbar ist, dass man ihn halbwegs vergessen kann -
Microsoft - work on it!
Funktionsweise
Tja, der Sternenhimmelstuermer achtete weitgehend auf die Hürden und
entwickelte folgendes Sysem:
Zerlege den Pfad (dospfad.txt)
,Dateinamen(predname.txt)
und Dateiendung (dtendung.txt)
mit Bordmitteln.
Zähle die Buchstaben des Originalpfades aus oder
set destination=%~dp0%
>"%destination%zhlprd.bat"
ECHO @echo off
>>"%destination%zhlprd.bat"
ECHO setlocal enabledelayedexpansion
>>"%destination%zhlprd.bat"
ECHO set /p String=^<predname.txt
>>"%destination%zhlprd.bat"
ECHO call :StrLength %%String%%
>>"%destination%zhlprd.bat"
ECHO set /a
StrLength=%%StrLength%% +4
>>"%destination%zhlprd.bat"
ECHO echo
%%StrLength%% ^>zprd.txt
>>"%destination%zhlprd.bat"
ECHO exit
>>"%destination%zhlprd.bat"
ECHO goto :eof
>>"%destination%zhlprd.bat"
ECHO :StrLength
>>"%destination%zhlprd.bat"
ECHO set tmpString=%%*
>>"%destination%zhlprd.bat"
ECHO set Length=0
>>"%destination%zhlprd.bat"
ECHO :StrLengthLoop
>>"%destination%zhlprd.bat"
ECHO if not "!tmpString:~%%StrLength%%,1!"=="" (
>>"%destination%zhlprd.bat"
ECHO set /a StrLength += 1
>>"%destination%zhlprd.bat"
ECHO goto StrLengthLoop
>>"%destination%zhlprd.bat"
ECHO )
>>"%destination%zhlprd.bat"
ECHO goto :eof
>>"%destination%zhlprd.bat"
ECHO :Ende
start /wait zhlprd.bat
del zhlprd.bat
Die hier angegebene Batch wurde von einer anderen Webseite übernommen und angepasst.
Dann wird der bloße Dateiname zu einem Fake-Dokument konvertiert (for /f "delims=" %%I in
(predname.txt) do echo %%I >>"%%I".tnt).
Die Dateiendung bei diesem Dokument ist egal - statt *.tnt könnte da auch *.gut
stehen...
Dieser Fake ist nötig, um den Dateinamen in Dos zu ermitteln, der nach
ein wenig konvertierung in DOS-Name.txt befindet...
Richtig schwierig wird es dann, die richtige Kennziffer, als zu
ermitteln, was nach dem Tildezeichen passiert. Im *.tnt wird z. B. PROBES~1.pdf
ermittelt, weil es ja nur ein Dokument mit diesem Namen gibt.
Es könnten aber mehrer Dateien im Ordner mit ähnlichen Namen vorliegen
z. B.
C:\Users\MANFRE~1\Desktop\DOSPFA~1\vers\PROBES~2.pdf
C:\Users\MANFRE~1\Desktop\DOSPFA~1\vers\PROBES~3.pdf
C:\Users\MANFRE~1\Desktop\DOSPFA~1\vers\PROBES~1.pdf
Also muss nun eine Bereinigung der Standard 1 erfolgen, was der
Sternenhimmelstuermer nun mit try und error bereinigt:
Er fragt nach :ausstieg einfach die Pfade so lange ab, bis kein
Dokument mehr vorliegt. Im einfachsten Fall liegt parallel im Ordner
des ermittelnden Verzeichnis nur ein Dokument vor. Da die Nummerierung
in jedem Verzeichnis durchgängig ist, fragt der Sternenhimmelstuermer
eben auf Dos-Ebene ab, ob ein Dokument mit 2,3,... vorliegt. Lautet die
Antwort nein, bricht die Schleife ab.
Danach wird die Anzahl der Treffer in einzelne Dokumente aufgelöst. Für
jeden Dateinamen in Klarschrift wird die Buchstabenzahl ermittelt
- dazu wird der Klarname anhand des Dos-Namens mit dir /b ermittelt.
Darauf werden die Buchstaben dieser Dokumente gezählt und mit den
gezählten des *.tnt abgeglichen.
Stimmt die Buchstabenzahl überein, dann geht der Sternenhimmelstuermer
davon aus, dass es sich um das richtige Dokument handelt und das
betreffende Ergebnis wird dem User angezeigt.
Das klappt sehr gut, aber ein direkter Buchstabenabgleich wäre valider
- ist aber auch schwerer, da zwischenzeitlich beim konvertieren aus ö
z. B. " entsteht..., die Methode des Sternenhimmelstuermers ist
teilweise sicherer...
Nachtrag 24.02.2014
Bugbereinigung
Der Autor vergaß eine Routine für den Fall, dass der DOS-Name bereits
DOS-Konform vorliegt. Dann ist natürlich eine 1 mit Tilde ein sicheres
Knockout für einen Fehler - warum meldet man das dem Autor nicht früher?
Na, jedenfalls schrieb der Autor eine Ausgleichsroutine und integrierte
Sie in die obige Batch, die jetzt höchst zuverlässig arbeitet:
set /p oneproof=<ihrdospfad.txt
if exist %oneproof% goto daswars
for /f %%a in (dospfad.txt) do for /f %%i in (predname.txt) do echo %%a%%i>>norml.txt
for /f %%a in (norml.txt) do for /f %%i in (dtendung.txt) do echo %%a%%i>ihrdospfad.txt
:daswars
Fer Autor ist faul und überprüft, ob ein valider Pfad herauskommt:
set /p oneproof=<ihrdospfad.txt
if exist %oneproof% goto daswars
Ist so eine Art error-level-Prüfung ohne errorlevel. Ja, denn der Pfad
liegt im Dosformat bereits im Dokument (ihrdospfad.txt) vor und wenn
der existiert, dann werden die nächsten Zeilen übersprungen: Ja, der
exist-Befehl kann auch den kompletten Pfad mit Dateinamen probieren und
nicht nur den Dateinamen allein, dass muss man wissen, weil man sonst
mit error level arbeiten muss ....
Existiert also z. B. das Dokument klein~1.pdf als Ergebnis
nicht, dann liegt das PDF-Dokument als klein.pdf im Doskonformen
Namen bereits vor und braucht nicht konvertiert werden.
Die Batch zäumt das Pferd also von hinten auf und prüft erstmal, ob
ähnliche Dokumente vorliegen, um dann bei einigen Dateien, deren
Dateiname Doskonform ist (nicht aber unbedingt der Pfad, was im
folgenden berücksichtigt wird...):
for /f %%a in (dospfad.txt) do for /f %%i in (predname.txt) do echo %%a%%i>>norml.txt
for /f %%a in (norml.txt) do for /f %%i in (dtendung.txt) do echo %%a%%i>ihrdospfad.txt
Wenn der Dateiname also im fiktiven Aufruf durch exist nicht
funktioniert, dann bastelt der Autor also als letzte Möglichkeit wieder
einen Doskonformen Pfad und Dateinamen und die Dateiendung zusammen und
lässt so die Tilde herausfallen - easy, nicht?
Das geht leider nicht mit einem einfachen set Befehl, da die einzelnen
Variablen Leerzeichen bei Verwendung von set /p
=<%var1%%var2%%var3%, da dann immer so dämliche Leerzeichen erzeugt
werden: Das ist das Tolle am for-Befehl, bei dem man aus zwei
einzeiligen Dokumenten %%a und %%i ohne Leerzeichen zusammensetzen
kann!
Dann wird in der ersten Zeile aus Pfad und Dateiname eben Pfaddateiname
und dieses im nächsten Dokument, dass von der For -Schleife
überschrieben wurde (deshalb nur ein >), PfaddateinameDateiendung.
Da ist die Tilde mit der eins dann nicht mehr drin und mit 99 % ist
dieses Ergebnis nun auch in dem Fall richtig, wo der Dateiname
DOS-Konform ist, ein Umstand, den der Autor nicht berücksichtigte,
während beim Pfad das berücksichtigt wurde - diese Möglichkeit war dem
Autor, der zuweilen in höheren Regionen schwebt, wahrscheinlich zu
trivial... wer es nicht versteht zur Beruhigung - das ist schon etwas
komplizierter, aber die Lösung im Nachhinein gesehen einfach...
Fazit
Für den Privatmann reicht die Methode des Sternenhimmelstuermers, für
Admins mit hunderten Dokumenten geht es eher über die am Anfang
vorgestellte zwei Zeilenmethode der Erstellung einer Liste des
Verzeichnisses.
Das Modul arbeitet fehlerfrei, ist in beliebigen Verzeichnissen
einsetzbar und find jeden Dos-Pfad auf ihrem System recht zuverlässig.
Es gibt aber auch durchaus ungünstige Konstellationen, wo es nicht
klappt, wo ein Durchschnittsuser aber selten Probleme haben wird.
Der Sternenhimmelstuermer hat 2013 ein Modul geschrieben. Daran sieht
man, dass die Erstellung für viele Batchschreiber eine unüberwindliche
Hürde darzustellen scheint.
In Abständen schreibt der Sternenhimmelstuermer solche Batches - letzte
war ein Dublettenfinder
in Batchform. Nach wie vor ist der Sternenhimmelstuermer einer der
weltweit innovativsten Programmierer im Sub-Level-Berich...
Haftungsausschluss - Das verwenden von Tipps oder Software auf dieser Seite auf eigene Gefahr.