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.




 
Impressum
Datenschutz