98697
Goto Top

PATH-Variable zerlegen und durchsuchen

Zerlegen der %PATH%-Systemvariable und gleichzeitiges Durchsuchen der jeweiligen Teilstrings

Hallo zusammen,

Ich beschäftige mich jetzt seit circa einer Woche tiefer mit Batch-Dateien und habe mittlerweile ein recht ansehnliches Programm hinbekommen.
Dabei habe ich mir jede Menge Tipps und Beiträge aus diesem Forum zunutze gemacht, weshalb ich mir sicher bin dass auch mein Problem zu
den schnell löslichen zählt wenn man sich etwas besser auskennt.

Mein Problem:

Ich möchte die Systemvariable %PATH% zerlegen und mir den Teilstring, wenn er einen bestimmten Teil einer Pfadangabe enthält, sichern.
Der letzte Teil des Pfads soll dann noch entfernt werden sowie die Schleife verlassen werden. Dies ist bei meinem derzeitigen Konstrukt jedoch
das Hauptproblem. Ich kann innerhalb meiner Schleife nicht auf die Variable "PFAD" zurückgreifen, ein "set PFAD" zeigt mir jedoch deren Inhalt korrekt an.

Mein Pseudocode:
beginn der schleife
zerlege PATH bei ";" in TEIL  
durchsuche TEIL auf "\ora92\bin\"  
wenn enthalten setze PFAD = TEIL
wenn "%PFAD%\sqlplus.exe\" existiert verlasse Schleife  
ende der schleife

entferne "bin\" von PFAD  

Soweit mein Vorhaben. Jetzt kommt mein Quellcode.
Ich bin mir sicher dass er alles andere als sauber programmiert ist, aber mehr kriege ich noch nicht auf die Kette.
Ich bin soweit dass der richtige TEIL der Variable PFADzugewiesen wird. Jedoch kriege ich die Abbruchbedingung nicht hin, da PFAD angeblich keinen Wert
hat. Weiterhin wird PATH nicht nur beim Trenn- sondern auch beim Leerzeichen getrennt. Das ist jedoch ersteinmal nebensächlich.

@echo off
@echo off
::
For /f "delims=; tokens=*" %%a in ("%path%") do for %%1 IN (%%a) DO (  

echo "%%1" | @find /I /C "ora92\bin" > nul  
if not errorlevel == 1 set pfad=%%1 
::Dieser Abbruch wird nicht ausgeführt, da %pfad% anscheinend erst nach der Schleife einen Wert erhält
if exist "%pfad%\sqlplus.exe" goto :erfolg  
)

echo Pfad nicht gefunden!
pause
goto :eof

:erfolg
echo Pfad gefunden!
::Hier sollte er jetzt noch das "bin" vom Pfad entfernen  
set pfad
pause
goto :eof

:eof

Ich hoffe dass mein Vorhaben halbwegs verständlich geblieben ist, wenn nicht fragt gerne nach.


Vielen Dank schonmal,


Smithy69123

Content-Key: 163245

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

Ausgedruckt am: 28.03.2024 um 19:03 Uhr

Mitglied: bastla
bastla 23.03.2011 um 17:14:23 Uhr
Goto Top
Hallo Smithy69123 und willkommen im Forum sowie als Batcher!

Dass %pfad% innerhalb der Schleife zwar einen Wert erhält, dieser aber nicht ausgelesen wird, ließe sich zwar per "delayedExpansion" ändern - allerdings brauchst Du diese Variable (zwischendurch) ja eigentlich genauso wenig wie die zweite "for"-Schleife (die bei Pfaden mit Leerzeichen im Namen ja sogar kontraproduktiv wäre) - es sollte doch auch (ungetestet)
for /f "delims=; tokens=*" %%a in ("%path%") DO echo %%a|find /i "\ora92\bin">nul && (set "Pfad=%%~a" & if exist "%%~a\sqlplus.exe" goto :erfolg)
genügen - wobei ich allerdings den Sprung aus der Schleife vermeiden und daher etwa so vorgehen würde:
set "Pfad="  
for /f "delims=; tokens=*" %%a in ("%path%") do for %%1 IN (%%a) DO echo %%a|find /i "\ora92\bin">nul && if exist "%%~a\sqlplus.exe" set "Pfad=%%~a"  
if not defined Pfad echo Pfad nicht gefunden! & pause & goto :eof
echo Pfad gefunden!
Hinsichtlich des Entfernens von "\bin": Wie soll das Ergebnis weiter verwendet werden, bzw stört ein "\" am Ende des gekürzten Pfades?

Grüße
bastla
Mitglied: 98697
98697 23.03.2011 um 18:11:02 Uhr
Goto Top
Hallo,
erst einmal vielen Dank für die schnelle Antwort.
Da ich mich mittlerweile nach Hause bewegt habe musste ich das ganze mal etwas abändern. Ich suche statt "\ora92\bin" jetzt einfach nach "\system32" und prüfe statt der Existenz von "\sqlplus.exe" mal auf die von "\ping.exe".

Dein zweiter Vorschlag hat mir schon ein ganzes Stück weitergeholfen und ist auch deutlich übersichtlicher als dieser Würfelhusten, den ich da fabriziert habe.
Nur in der zweiten Schleife war ein kleiner Fehler, aber den habe ich mittlerweile auch entdeckt: Statt der Angabe %%~a muss in der inneren Schleife %%~1 verwendet werden. So sieht der Code dann jetzt aus:
set "Pfad="   
for /f "delims=; tokens=*" %%a in ("%path%") do for %%1 IN (%%a) DO echo %%1|find /i "\system32">nul && if exist "%%~1\ping.exe" set "Pfad=%%~1"  
if not defined Pfad echo Pfad nicht gefunden! & pause & goto :eof 
echo Pfad gefunden! & set pfad & pause
:eof
Aber wenn man sich %%1 vor der Übergabe an das find-Kommando durch ein echo ausgeben lässt bemekt man immernoch die Trennung bei Leerzeichen im Dateipfad. Beim system32-Pfad kommen ja keine vor, hier wird der Pfad bereits einwandfrei ausgelesen.
Ein "\" am Ende des gekürzten Pfads stört übrigens nicht, ist sogar erwünscht. Aber mir fielen hier jetzt nur Varianten ein, die ungefähr so komplex waren wie mein Anfangscode und dabei die Flexibilität einer Stahlbetondecke mit sich gebracht haben.

Dankeschön,

Smithy69123
Mitglied: bastla
bastla 23.03.2011 um 19:01:42 Uhr
Goto Top
Hallo Smithy69123!

Sorry - vergiss gleich mal, was ich da oben produziert respektive gepasted habe ... face-sad

Die Zeile 2 sollte eigentlich einfach so aussehen:
for %%a in ("%path:;=";"%") do echo %%a|find /i "\ora92\bin">nul && if exist "%%~a\sqlplus.exe" set "Pfad=%%dp~a"
Hintergrund: Da eine "gewöhnliche" "for"-Schleife auch anhand von ";" trennt, muss nur dafür gesorgt werden, dass Pfade mit Leerzeichen nicht "zerrissen" werden - daher einfach alle Semikola durch ";" ersetzen und am Anfang und Ende auch jeweils ein Anführungszeichen ergänzen - dann enthält %%a jeweils einen Pfad unter Anführungszeichen und daher komplett.

Da sich dann der Pfad schon in der Schleifenvariablen befindet, kann auch gleich "bin" eliminiert werden, indem nur Laufwerk und Pfad verwendet werden (soferne sich nicht am Ende des "path"-Eintrages schon ein "\" befindet) - ansonsten die "Sicherheitsvariante":
for %%a in ("%path:;=";"%") do echo %%a|find /i "\ora92\bin">nul && if exist "%%~a\sqlplus.exe" set "Pfad=%%~a"  
if not defined Pfad echo Pfad nicht gefunden! & pause & goto :eof
if "%Pfad:~-1%"=="\" set "Pfad=%Pfad:~0,-1%"  
for %%a in ("%Pfad%") do set "Pfad=%%~dpa"  
Noch kurz zur Erklärung von "%%~dpa": Wie am Ende der Hilfe zu "for" nachzulesen, wird mit "d" das Laufwerk ("drive") und mit "p" der Pfad ("path") aus dem Inhalt von %%a extrahiert - dabei wird alles vom Beginn bis zum letzten "\" (inklusive) als Laufwerk + Pfad interpretiert (alles danach als Name + Extension). Wenn nun der gefundene Pfad am Ende einen "\" aufweist, würde diese Zerlegung keinen Erfolg haben (weil ja 'alles bis zum letzten "\"' verwendet wird) - daher muss vorweg ein abschließender "\" abgeschnitten werden - Infos dazu gibt's per "set /?" ...

Grüße
bastla
Mitglied: 98697
98697 23.03.2011 um 19:53:04 Uhr
Goto Top
Hallo bastla,

ich muss zwar zugeben dass ich den Teil mit dem Ersetzen nicht mehr ganz verstanden habe, aber es funktioniert einwandfrei.
Es ist (wenn ich das nach anderthalb Wochen schon sagen darf face-smile ) immer wieder überraschend was dieser for-Befehl noch so alles kann. Den Teil mit ~dp hatte ich auch schon entdeckt. Aber das hier "%path:;=";"%" werde ich mir auf jeden Fall noch mal zu Gemüte führen müssen.

Vielen Dank für deine schnelle und gute Hilfe.

Smithy69123
Mitglied: bastla
bastla 23.03.2011 um 19:58:27 Uhr
Goto Top
Hallo Smithy69123!

Die schnelle Hilfe war leider nicht gut ...

Zum Ersetzen wirst Du auch mit "set /?" fündig, und bei weiteren Fragen: fragen ... face-wink

Grüße
bastla
Mitglied: Biber
Biber 23.03.2011 um 21:09:58 Uhr
Goto Top
Moin Smithy69123,

willkommen im Forum auch von mir.

Wenn du dich doch ohnehin gerade spielerisch an die schlichte Eleganz der FOR-Anweisung herantastest,
dann spendier ich noch zwei Oneliner vom CMD-Prompt, um andere Strategien aufzuzeigen.

[Am CMD-Prompt; führendes ">" nicht mit eingeben, ist sich mein Prompt]
(=21:03:04  D:\temp=)
>@for %i in ("%path:;=";"%") do @If exist "%i\sqlplus.exe" @echo %~dpi|findstr /i "ora"
C:\Oracle\Home\10.2\


(=21:03:14  D:\temp=)
>for %i in (sqlplus.exe) do @for %j in (%~dp$PATH:i..\) do @echo %~dpj|findstr /i "ora"
C:\Oracle\Home\10.2\

Die erste Variante sucht "nur" nach der sqlplus.exe im Pfad... der Pfad darüber (also oberhalb ....\bin\)
steht in dem "echo %~dpi" und kann gefiltert werden nach "ora92" bei dir, nach "ora" bei mir.
Ansonsten ist es genau der Weg, den bastla oben verwendet hat.

Die zweite Variante finde ich etwas charmanter.. die bedient sich der eher seltener verwendeten %~dp$PATH:i-Syntax.

Das Geheimnis beim Bätchen ist: Nicht soviel Heckmeck drum machen. face-wink

Grüße
Biber