highend01
Goto Top

Schleife wird nicht ausgeführt und ein paar andere Kleinigkeiten

Hallo zusammen,

Ich hoffe Ihr könnt mir dabei helfen, ein wenig Licht ins Dunkel der Batchprogrammierung zu bringen face-smile

Hintergrund des Scriptes ist, dass ich unter Linux zur Sicherung künftig DAR (Disk Archiver) einsetzen will und die Archive künftig zur Not auch unter Window entpacken können will und das aus Bequemlichkeit per Kontextmenü bei einem Rechtsklick auf ein solches.

Dafür wird in der Registry ein entsprechender Aufruf eingebaut:

[HKEY_CURRENT_USER\Software\Classes\Disk Archiver Image File\shell\Extract to <directory>\command]
@="\"D:\\Work\\Tools\\DAR\\dar_extract.bat\" \"%1\""

(das ist jetzt natürlich nur der <command> Teil, den Rest habe ich aus Platzgründen weggelassen. Der Aufruf des Scriptes beim Rechtsklick auf ein .dar Archiv funktioniert auch soweit korrekt.

Kommen wir zum Script:

@echo off
set sComplete=%1

for %%i in ("%sComplete%") do set sPathOnly=%%~di%%~pi
for %%i in ("%sComplete%") do set sFileNameFull=%%~ni%%~xi
for /F "delims=. tokens=1" %%i in ("%sFileNameFull%") do set sFileNameShort=%%i


REM echo sPathOnly="%sPathOnly%"
REM echo sFileNameFull="%sFileNameFull%"
REM echo sFileNameShort="%sFileNameShort%"


@rem D:\Work\Tools\DAR\glftpd_full.1.dar
@rem > /cygdrive/d/work/tools/dar/

set linPath1=%sPathOnly:\=/%
echo linPath1=%linPath1%
set linPath2=%linPath1::=%
echo linPath2=%linPath1%


@mkdir %sFileNameShort%
@rem "D:\Work\Tools\DAR\DAR.exe" -R ./ -v -w -O -x %sFileNameShort%"

---

Wenn ich einen Command Prompt mit aktivem Verzeichnis in D:\Work\Tools\DAR offen habe und das Script manuell ausführe (mit dar_extract.bat D:\Work\Tools\DAR\glftpd_full.1.dar) läuft es durch. Wenn ich es allerdings über das Kontextmenü beim Klick auf die Datei ausführe kommt es nur bis zur zweiten for Schleife.

for /F "delims=. tokens=1" %%i in ("%sFileNameFull%") do set sFileNameShort=%%i

Wird schon nicht mehr ausgeführt (getestet mit pause um zu sehen bis wo er kommt). Warum mag er die Zeile nicht und wie ändere ich sie?

Als zweites würde ich gerne wissen, wie ich die Variable sPathOnly (die beim manuellen Aufruf "D:/Work/Tools/DAR/" beinhaltet auf das Format umschreibe, was DAR voraussetzt ("/cygdrive/d/work/tools/dar/"). Meine erste Umwandlung der Backslashes in Slashes (set linPath1=%sPathOnly:\=/%) funktioniert ja noch, danach geht aber nicht mehr viel (die nächste Zeile scheitert beim Entfernen des Doppelpunktes im Pfad).

Wenn der Pfad korrekt umgeschrieben worden ist, würde ich ihn in der letzten Zeile als Variable (sPathOnly + sFileNameShort anstatt des ./ verwenden und dann das eigentlichen Entpacken damit "freischalten"... Das -x %sFileNameShort% in der Zeile setzt voraus, dass das Verzeichnis bereits existiert, weshalb auch vorher das mkdir dafür aufgerufen wird.

Das Ganze unter Windows XP (Pro).

Vielleicht hat ja jemand ein paar Hilfestellungen für mich oder auch Vorschläge, wie man so etwas intelligenter (schäm face-sad ) angehen könnte?

LG,
Highend01

Content-ID: 67603

Url: https://administrator.de/contentid/67603

Ausgedruckt am: 18.12.2024 um 19:12 Uhr

Biber
Biber 01.09.2007 um 01:52:48 Uhr
Goto Top
Moin Highend01,

willkommen im Forum.

Den Anfang kann ich ja machen...

Bitte ändere in der Registry:
>[HKEY_CURRENT_USER\Software\Classes\Disk Archiver Image File\shell\Extract to <directory>\command]
>@="\"D:\\Work\\Tools\\DAR\\dar_extract.bat\" \"%L\""

Im Script:
@echo off & setlocal
REM set sComplete=%1
@echo Just for test: [%*]

for %%i in (%*) do set "sPathOnly=%%~dpi"  
for %%i in (%*) do set "sFileNameFull=%%~nxi"  
...
REM ..... hier erstmal "Pause"  
Echo Debug sPathonly: [%sPathOnly%] sFileNameFull: [%sFileNameFull%]
pause
goto :eof 
for /F "delims=. tokens=1" %%i in ("%sFileNameFull%") do set sFileNameShort=%%i  
[Ungetestete Skizze]
Zum unteren Teil kommen wir, wenn der obere Part soweit fliegt.

Grüße
Biber,
dessen Becks wartet...
Highend01
Highend01 01.09.2007 um 02:15:59 Uhr
Goto Top
Hallo und danke für das Willkommen im Forum, Biber face-smile

Hab den Registry Eintrag geändert und das Script umgeschrieben:

Ausgabe beim Ausführen über die Kontextmenüerweiterung:

Just for test: ["D:\Work\Tools\DAR\glftpd_full.1.dar"]
Debug sPathonly: [D:\Work\Tools\DAR\] sFileNameFull: [glftpd_full.1.dar]
Drücken Sie eine beliebige Taste . . .

Gruß und ich hoffe das Becks ist eiskalt (<- liebt kalte Getränke) :D

LG,
Highend01
Biber
Biber 01.09.2007 um 03:02:27 Uhr
Goto Top
Moin Highend01,

na ja, klappt doch schon 5 Zeilen weit... *ggg

Lass uns trotzdem nach dem Frühstück weitermachen.

Biber,
der die Praktikantinnenbetreuung sehr ernst nimmt und sich jetzt erstmal darum kümmern muss...
Highend01
Highend01 01.09.2007 um 03:49:53 Uhr
Goto Top
Rehuhu,

mh, schon fast 4 aber ich war irgendwie nicht müde...

Es laufen nicht nur 5 Zeilen face-smile

Bin beim Suchen über die Technet Beiträge gestolpert (http://www.microsoft.com/technet/prodtechnol/Windows2000serv/support/FA ..)

Darunter dann: How do I parse a file name parameter into its' constituent parts?

Auf diese Art und Weise konnte ich die blöde Zeile mit "FOR /F "delims=. tokens=1" %%i in ("%sFileNameFull%") DO set sFileNameShort=%%i"
rauswerfen und splitte schon mit den normalen For Schleifen die Eingangsvariable %* auf.

Ich hab noch zwei zusätzliche Aufsplittungen vorgenommen und damit ist es dann auch ein Leichtes, den für Cygwin notwendigen Pfad neu
zusammen zu setzen.

Alles in allem sieht das Script jetzt folgendermaßen aus:
@echo off & setlocal

REM Anfangsvariablen setzen
set DAR="D:\Work\Tools\DAR\DAR.exe"  
set Cygdrive="/cygdrive/"  

::echo Just for test: [%*]

REM %* in seine Bestandteile aufsplitten
for %%i in (%*) do set "sPathOnlyOld=%%~pi"  
for %%i in (%*) do set "sPathFull=%%~dpi"  
for %%i in (%*) do set "sFileNameFull=%%~nxi"  
for %%i in (%*) do set "sFileNameShortOld=%%~ni"  
for %%i in (%*) do set "sDriveLetterOld=%%~di"  

REM Pfade / Namen in den Variablen ersetzen
set sPathOnly=%sPathOnlyOld:\=/%
set sDriveLetter=%sDriveLetterOld:~0,-1%
set sFileNameShort=%sFileNameShortOld:~0,-2%


REM Outputs für Debugzwecke
::Echo Debug sPathOnly: [%sPathOnly%] sPathFull: [%sPathFull%] 
::Echo Debug sFileNameFull: [%sFileNameFull%]
::Echo Debug sFileNameShort: [%sFileNameShort%] sDriveLetter: [%sDriveLetter%]

REM Variable für den auf Linux Art umgeschriebenen Pfad setzen
set linPath=%Cygdrive%%sDriveLetter%%sPathOnly%%sFileNameShort%

REM Verzeichnis erstellen und entpacken
mkdir %sPathFull%%sFileNameShort%
%DAR% -R %linPath% -w -O -x %sFileNameShort%"  

Ich glaub für heute ist das schon ziemlich zufriedenstellend. Hättest du noch Verbesserungsvorschläge?

LG,
Highend01
Biber
Biber 01.09.2007 um 10:58:41 Uhr
Goto Top
Moin Highend01,

<OT>
ich hatte auch nichts davon geschrieben, dass ich müde wäre oder sofort schlafen wollte...
</OT>

Verbesserungsorschläge bzw. Anmerkungen:
  • Ich habe Deinen Code in entsprechende Code-Tags gesetzt. Möglichkeiten siehe unter "Häüfige Fragen - Formatierungshilfen".

  • Bei den SET-Zuweisungen, bei denen ich immer die Set-Anweisung incl. Variablen in Anführungszeichen setze, muss ich dazu sagen: Das ist eine persönliche Vorliebe von mir, von M$ weder dokumentiert noch empfohlen. Siehe Hilfe von SET (Set /?).

  • Das Setzen der %~ni, %~xi...-Parameter kann auf jeden Fall etwas verkürzt werden. Siehe unten.

  • Und wenn gewährleitet WÄRE, dass nur ein Parameter ankommt, wäre es ganz ohne FOR-Konstrukt machbar ( set "sPathOnlyOld=%~p1"). Ich würde allerdings vor dieser Vereinfachung auf jeden Fall testen, ob es dann auch mit Parametern wie "Y:\Eigene Dateien\xy.abc" klappt, also mit Dateien, die Leerzeichen im Pfad/Namen haben.

  • bei dem sFileNameShortOld musst Du wissen, welche Konvention Du einbauen willst - entweder den "Dateinamen ohne Endung" oder den" Dateinamen bis zum ersten Punkt von links gesehen". Da ist von der ersten Version zur jetzigen ein kleine Unterschiedlichkeit.

@echo off & setlocal

REM Anfangsvariablen setzen
set DAR="D:\Work\Tools\DAR\DAR.exe"  
set "Cygdrive=/cygdrive/"  

::echo Just for test: [%*]

REM %* in seine Bestandteile aufsplitten
for %%i in (%*) do ( 
    set "sPathOnlyOld=%%~pi"  
    set "sPathFull=%%~dpi"  
    set "sFileNameFull=%%~nxi"  
    set "sFileNameShortOld=%%~ni"  
    set "sDriveLetterOld=%%~di"  
)
REM Pfade / Namen in den Variablen ersetzen
set sPathOnly=%sPathOnlyOld:\=/%
set sDriveLetter=%sDriveLetterOld:~0,-1%
set sFileNameShort=%sFileNameShortOld:~0,-2%


REM Outputs für Debugzwecke
::Echo Debug sPathOnly: [%sPathOnly%] sPathFull: [%sPathFull%] 
::Echo Debug sFileNameFull: [%sFileNameFull%]
::Echo Debug sFileNameShort: [%sFileNameShort%] sDriveLetter: [%sDriveLetter%]

REM Variable für den auf Linux Art umgeschriebenen Pfad setzen
set linPath=%Cygdrive%%sDriveLetter%%sPathOnly%%sFileNameShort%

REM Verzeichnis erstellen und entpacken
mkdir "%sPathFull%%sFileNameShort%"  
%DAR% -R %linPath% -w -O -x %sFileNameShort%

Grüße
Biber
Highend01
Highend01 02.09.2007 um 10:50:57 Uhr
Goto Top
Sodele, da bin ich auch wieder (sorry für die späte Rückmeldung!) face-smile

Frank, vielen lieben Dank für die Anmerkungen und ausführlichen Erklärungen!

  • Und wenn gewährleitet WÄRE, dass nur ein Parameter ankommt, wäre es ganz ohne FOR-Konstrukt machbar ( set "sPathOnlyOld=%~p1"). Ich würde allerdings vor dieser Vereinfachung auf jeden Fall testen, ob es dann auch mit Parametern wie "Y:\Eigene Dateien\xy.abc" klappt, also mit Dateien, die Leerzeichen im Pfad/Namen haben.

Ich finde die FOR-Konstruktion schon ganz in Ordnung auch wenn ich sicher sein kann, dass immer nur ein Parameter übergeben wird. Ich hatte immer nur mit einem File getestet, welches weder im Pfad noch im Namen Leerzeichen aufwies und bin dann prompt über kleinere Probleme gestolpert, als ich dann einen Pfad mit Leerzeichen genommen hab. Durch Verwendung von "" für die Variablenzuweisungen funktioniert das jetzt aber auch einwandfrei.

  • bei dem sFileNameShortOld musst Du wissen, welche Konvention Du einbauen willst - entweder den "Dateinamen ohne Endung" oder den" Dateinamen bis zum ersten Punkt von links gesehen". Da ist von der ersten Version zur jetzigen ein kleine Unterschiedlichkeit.

So wie es jetzt ist, ist es gut. DAR arbeitet automatisch mit sogenannten Slices und fängt bei der Numerierung immer mit 1 an. Da man für das Entpacken des Archives aber nicht den vollen Dateinamen inkl. Sliceendung angeben darf (dürfen schon, dann erfolgt aber eine Sicherheitsabfrage), sondern den sogenannten Basename (d.h. ohne die .SliceNummer.dar Endung), ist das Kürzen des Namens um 2 Zeichen von Hinten gesehen schon in Ordnung (nach der Aufsplittung natürlich, die dann eh schon den Dateinamen ohne Endung zurückliefert.


Eine Sache könnte ich noch brauchen: Eine Fallunterscheidung, ob das gewählte Archiv von einem lokalen Datenträger oder von einem Netzlaufwerk stammt. Die Übersetzung des Pfadnamens bei lokalen Datenträgern in die "Cygwin" Variante funktioniert ja so weit einwandfrei. Wenn man allerdings ein Archiv wählt, das auf einem Samba Share liegt, dann muss die Notation für den Pfad auf diese Weise umgesetzt werden: \\host\file\path -> \\\\host/file/path.

Eine Idee, wie man das am besten einbaut?

Abgesehen davon werden Dateinamen wohl auch eine Zeitangabe im Format %H:%M:%S beinhalten können. Da Muss ich auch noch mal prüfen, ob das Script das erkennen kann und die Doppelpunkt in ein anderes Zeichen vorher wandelt (Windows mag ja keine Doppelpunkte in Pfaden oder Dateinamen)...

LG,
Highend01
Biber
Biber 02.09.2007 um 14:19:58 Uhr
Goto Top
Moin Highend01,

zu den verbleibenden Sonderfällen:
  • >Wenn man allerdings ein Archiv wählt, das auf einem Samba Share liegt, dann muss die Notation für den Pfad auf diese Weise umgesetzt werden: \\host\file\path -> \\\\host/file/path.

Da kommt uns ein zugesichertes M$-Feature zugute - die Implementierung der CMD-Funktionalität ist genauso strohdoof wie der Rest.
Bedeutet, wenn ein -ich sag mal volkstümlich- Textparameter durch den %~dpnx-Variablenauflösungsprozess gejagt wird, dann ergibt sich:
Z:\>
$cmd$for /f %i in ("\\xxserver\yyshare\test.abc") do @echo [Drive:%~di] [Path:%~pi] [File:%~nxi]  
[Drive:\\] [Path:xxserver\yyshare\] [File:test.abc]
> wenn der Parameter %~di == Drive bei Dir als "\\" ankommt, dann liegt dort "\\" vor.
> If [%sDriveLetterOld%]=="\\" set "sDriveLetterOld=\\\\"

Falls Du allerdings diesen UNC-Path noch nicht vorliegen hast, sondern erst auflösen musst, dann suche mal mit der Forumssuche nach "UNC-Pfad" oder "UNCpath.vbs".
Damit wird dann z.b. aus einem Netz-File "W:\Dokus\abc.text" das UNC-File "\\xxserver\yyshare\Dokus\abc.text" rekonstruiert.
Das wäre mit native Batch zu umständlich und zu unsauber, da sollte ein VBS-Schnipsel rein.

  • >Windows mag ja keine Doppelpunkte in Pfaden oder Dateinamen...
Stimmt, es wird immer -egal ob im Zusammenspiel mit MacOS oder mit Unix ein paar Dateinamen Konventionen geben, die Du nachbehandeln musst.
Ich würde an dieser Stelle (Windows-Namenskonventionen sicherstellen) eigentlich so vorgehen, dass der Gesamt-FullQualifiedFilename getrennt wird in einen Laufwerks/Drive-Part ("\\" bzw: "C:" etc.) und einen Part "%~pnxi" ==RestOhneDrive.
Und im RestOhneDrive kannst Du wie oben alle ":" durch "_" usw. ersetzen wie Du wutt.
Und erst danach zerlegst Du den Gesamtstring "%drive%%RestOhneDriveNachbehandelt%" in diese Pfad-, Name-, Extension-Bestandteile.

Grüße
Biber