webglider
Goto Top

Trennzeichen in Variable zählen

Hallo zusammen!

Ich habe mich bereits durch eine unmenge an Forenbeiträgen gewühlt, meine Lösung habe ich allerdings noch nicht gefunden.

Folgende Aufgabe stellt sich mir:

Ich habe eine Systemvariable MY-PROG in der ein Verzeichnis definiert ist, z.B. c:\programme\myprog. Jetzt möchte ich eigentlich nur die Anzahl der \ im Ordnernamen der Variable My-Prog ermitteln. In diesem Fall also 3. Mit diesem Wert möchte ich dann in meiner Batch-Datei weiterarbeiten.

So sieht mein Code zurzeit aus:

@echo off

set count=0
for /f "delims=\" %%i in ('echo %MY-PROG%') do (set /a count+=1)  
echo %count%

Wenn ich den Code ausführe erwarte ich eine Ausgabe 3, es wird jedoch nur 1 ausgegeben. Die Schleife wird offensichtlich nur einmal durchlaufen. Wo liegt mein Denkfehler?

Content-Key: 114805

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

Ausgedruckt am: 28.03.2024 um 12:03 Uhr

Mitglied: bastla
bastla 27.04.2009 um 20:00:54 Uhr
Goto Top
Hallo webglieder und willkommen im Forum!

Da Du der Schleife nur eine Zeile (die Ausgabe der Variablen %MY-PROG%) übergibst, wird sie auch nur einmal durchlaufen ...

Was Du möchtest wäre eher:
@echo off & setlocal
set "MY-PROG=c:\Programme\myprog"  

set "MY-TEMP=%MY-PROG: =_%"  
for %%i in (%MY-TEMP:\=,%) do set /a count+=1
echo %count%
wobei auch in diesem Fall nicht die Anzahl der "\", sondern diese Anzahl + 1 ermittelt wird ...

Die Zeile 4 sorgt übrigens für den Fall vor, dass Leerzeichen im Pfad enthalten wären (falls auch noch ein oder mehrere "," vorkämen, müssten auch diese vorweg ersetzt werden).

Wozu brauchst Du eigentlich diese Anzahl?

Grüße
bastla
Mitglied: webglider
webglider 27.04.2009 um 20:21:38 Uhr
Goto Top
Perfekt, bastla. Das funktioniert.

Hintergrund:

Ich habe diverse Unterordner, in denen Batch-Skripte liegen. Diese sollen selbst ermitteln, in welchen Unterordner sie sich befinden. Dabei interessiert mich aber nur ein bestimmer Teil des ganzen Pfades, z.B.:

Ordner1\Unterordner1\Unterordner\datei.bat
Ordner1\Unterordner2\Unterordner\datei.bat

datei.bat soll selbst ermitteln, ob sie in Unterordner1 bzw. Unterordner2 liegt. Den Wert (Unterordner1 oder Unterordner2) möchte ich nun mit deiner ersten Hilfe aus %cd% extrahieren.
Mitglied: bastla
bastla 27.04.2009 um 20:28:07 Uhr
Goto Top
Hallo webglider!

Nur als Anmerkung: Der Pfad einer Batchdatei lässt sich über "%0" (bzw eine Zerlegung, etwa "%~p0" - siehe dazu gegen Ende der Online-Hilfe zu "for") ermitteln ...

Grüße
bastla
Mitglied: 77559
77559 27.04.2009 um 20:32:12 Uhr
Goto Top
Zitat von @bastla:
Die Zeile 4 sorgt übrigens für den Fall vor, dass Leerzeichen im Pfad enthalten wären (falls auch noch ein oder mehrere "," vorkämen, müssten auch diese vorweg ersetzt werden).

Das ginge einfacher auch so:
for %%i in ("%MY-TEMP:\=","%") do set /a count+=1  

Es müsste aber auch einheitlich KEIN abschließender Backslash am Pfad hängen.
und count sollte initialisiert werden
Set count=0

Gruß
Mitglied: webglider
webglider 27.04.2009 um 20:36:57 Uhr
Goto Top
Hallo LotPings, dein Code liefert bei mir aber leider als Ergebnis nur 1.
Mitglied: Biber
Biber 27.04.2009 um 20:39:32 Uhr
Goto Top
Moin webglider,

willkommen im Forum.

Hmmm, Du bringst hier beim Zählen zwei Vokabeln durcheinander, bei denen der CMD-Interpreter recht stur ist.

  • Das eine, was sich zählen lässt sind ZeiCHen. [ein Sonderfall von "Worte" bzw. "Token".
  • Das andere sind ZeiLen - dafür ist eine [FOR /F %i in (Text-ggf-mit-CRLF) do set /a Count+=1]-Anweisung prima.
Im zweiten Fall wird ja rechts des "DO" überhaupt nichts mit der Laufvariablen %i gemacht ... die Zeilenzahl hat ja wenig mit der Anzahl der tokens/Worte/zeichen zu tun.
Gezählt werden unterm Strich die relevanten/nichtleeren Zeilen.

Eine FOR-Anweisung [ohne /F] dagegen kann durchaus in der Klammer einzelne Elemente -egal ob eins oder sieben oder 13 verarbeiten
>FOR %i in ("bla" "blubb" 1234) do @echo %i  
"bla"  
"blubb"  
1234

Was Du also verwenden könntest, wäre eine FOR-ohne-/F-Anweisung mit einer Liste statt eines einzelnen Elements.

Zwei Ansätze (einmal mit FIND/C als Zählhilfe, einmal mit FOR pur):
[ich nehme mal %ALLUSERSPROFILE% statt %MY-PROG% zur Demo]
>(for %i in ("%allusersprofile:\=";"%") do @echo "\")|find /C "\"  
3
--- soweit das einfache... das Zählen bis 3
-- beim Schreiben in eine Variable wirds grottig... keine Chance ohne temporäres Speichern
>(for %i in ("%allusersprofile:\=";"%") do @echo "\")|find /C "\">anz&set /p anz=<anz&del anz&set anz  
anz=3
---> brauchen wir nicht weiter verfolgen... auch wenn der FIND /C uns hier das Zählen erleichtert.
Wenn eine temporäre Speicherung nötig ist, wird es albern.
[Ebenso wäre es es bei einem Stringlängenvergleich 'Länge mit "\" vs. Länge ohne "\" ' - geht auch nur mit Temp-Datei.]

Jetzt das empfohlene Beispiel:mit FOR ohne /F-Parameter:
set "cnt=" &for %i in ("%ALLUSERSPROFILE:\=";"%") do set /a cnt+=1  
-bzw mit Anzeige-
>@(set "cnt=" &for %i in ("%ALLUSERSPROFILE:\=";"%") do @set /a "cnt+=1")>nul &set cnt  
cnt=3
Wesentlich ist aber nur das Umwandeln des einzelnen Elements "%text%" bzw "%MY-PROG%" in eine Liste einzelner Elemente in Anführungszeichen.

Spiel es mal am CMD-Prompt durch mit
For %i in ("%MY-PROG:\=";"%") do @echo %i

Grüße
Biber
Mitglied: bastla
bastla 27.04.2009 um 20:40:34 Uhr
Goto Top
Hallo webglider!

LotPings meinte eigentlich die ursprüngliche Variable %MY-PROG% - damit sieht's dann gleich besser aus ...

Grüße
bastla
Mitglied: webglider
webglider 28.04.2009 um 17:26:30 Uhr
Goto Top
hmm... so richtig komme ich nicht weiter.

Nehmen wir folgendes Szenario:

Ich habe eine Verzeichnis c:\tool\kunde1\script.bat und ein Verzeichnis c:\tool\kunde2\script.bat. Die script.bat soll nun selbst erkennen, dass sie sich im Unterverzeichnis kunde1 oder kunde2 befindet.

Allerdings kann die Struktur auch manchmal so aussehen: c:\unterverzeichnis\tool\kunde1, die anzahl der Verzeichnisse ist also nicht zwingend gleich.

Wie realisiere ich sowas elegant ohne temp-dateien nutzen zu müssen?
Mitglied: 77559
77559 28.04.2009 um 17:42:08 Uhr
Goto Top
Zitat von @webglider:
Ich habe eine Verzeichnis c:\tool\kunde1\script.bat und ein Verzeichnis c:\tool\kunde2\script.bat. Die script.bat soll nun selbst erkennen, dass sie sich im Unterverzeichnis kunde1 oder kunde2 befindet.

  • Das ist nicht ganz klar, meinst du das eine Kopie der Batchdatei in dem Verzeichnis ist? Dann kannst du dies benutzen:
for %%A in ("%~p0") do set "Kunde=%%~nxA"  

  • Oder das dieses Verzeichnis das aktuelle Verzeichnis ist ?
for %%A in ("%CD%") do set "Kunde=%%~nxA"  

Allerdings kann die Struktur auch manchmal so aussehen:
c:\unterverzeichnis\tool\kunde1, die anzahl der Verzeichnisse ist also nicht zwingend gleich.
Willst du nur das letzte Verzeichnis haben? Dann funktioniert obiger Code in beiden Fällen

Gruß
LotPings
Mitglied: webglider
webglider 28.04.2009 um 18:34:20 Uhr
Goto Top
Es handelt sich um die exakt gleiche script.bat in beiden Verzeichnissen. Kannst du mir deinen Code näher erklären?

for %%A in ("%~p0") do set "Kunde=%%~nxA"  

Ich erhalte wenn ich deinen Code verwende die Meldung ECHO ist ausgeschaltet (OFF)

So sieht mein Versuch mit deinem Tipp aus:

@echo off

echo MY-PATH: %MY-PATH%
echo CURRENT-DIR: %CD%
for %%A in ("%~p0") do (set "KUNDE=%%~nxA")  
echo %KUNDE%

pause

Ausgabe:

MY-PATH: c:\programme\tool
CURRENT-DIR: c:\programme\tool\kunde1\batch
ECHO ist ausgeschaltet (OFF). <- Hier würde ich %KUNDE% erwarten?
Mitglied: miniversum
miniversum 28.04.2009 um 18:59:43 Uhr
Goto Top
Versuchs mal damit:
@echo off

echo MY-PATH: %MY-PATH%
echo CURRENT-DIR: %CD%
set "pfad=%~p0"  
for %%A in ("%pfad:~0,-1%") do (set "KUNDE=%%~nxA")  
echo %KUNDE%

pause
Mitglied: 77559
77559 28.04.2009 um 19:08:25 Uhr
Goto Top
Gerne,
aber du musst diese Batchdatei ausführen und alles was in Notepad erscheint,
ganz genau und mehrmals durchlesen.
Besser noch ausdrucken und als Bett- und Toilettenlektüre eine Woche lang durcharbeiten. face-wink

:: GetHelp.cmd
@echo off&setlocal
for /f "tokens=3 delims=:. " %%A in ('chcp') Do set OLD_CP=%%A  
chcp 1252
Echo ====================== Set ====================== >"%~dpn0.txt"  
set /? >>"%~dpn0.txt"  
Echo ====================== For ====================== >>"%~dpn0.txt"  
for /? >>"%~dpn0.txt"  
Echo ====================== Cmd ====================== >>"%~dpn0.txt"  
cmd /? >>"%~dpn0.txt"  
start "" Notepad "%~dpn0.txt"  
chcp %OLD_CP%

Also %0 ergibt den Namen der aktuell laufenden Batchdatei.
Für Kommandozeilenargumente %0 bis %9 sowie die Schleifenvariablen %%a bis %%z bzw %%A bis %%Z OTon: Wurde die Syntax zur Ersetzung von Verweisen auf FOR-Variablen erweitert. Ich nenne das lieber Tilde Funktionen.
"%~p0" extrahiert nur den Pfad ohne LW: NAme oder Extension.
Die for Variable %%A enthält also nur den Pfad-Bestandteil "tool\kunde2" oder "Unterverzeichnis\tool\kunde2" Für diesen Teil bedeutet die Verwendung von %%~nxA das extrahieren des letzten Ordners der hier nur als name.ext interpretiert wird. (ext für den Fall das der Ordnername einen Punkt enthält).

Bei weiteren Fragen einfach nochmal den Ausdruck durchlesen und dann erst posten face-wink

Gruß
LotPings

[Edit]miniversum hat meinen Fehler des noch anhängenden Backslash schon verbessert[/Edit]
Mitglied: Biber
Biber 28.04.2009 um 19:26:44 Uhr
Goto Top
... genau, und zum Üben noch diese beiden Variationen...
@echo off & setlocal

echo MY-PATH: %MY-PATH%
echo CURRENT-DIR: %CD% -- Batchdatei [%0]
for /d %%A in ("%~dp0\.") do set "KUNDE_v1=%%~nxA"  
for %%A in ("%~0\..") do set "KUNDE_v2=%%~nxA"  
set Kunde_v

pause

Beispielausgabe:
>e:\schnipsel\TestWoBinIch.cmd
MY-PATH:
CURRENT-DIR: D:\temp -- Batchdatei [e:\schnipsel\TestWoBinIch.cmd]
KUNDE_v1=Schnipsel
KUNDE_v2=Schnipsel
Drücken Sie eine beliebige Taste . . .

Grüße
Biber

[Edit]
Zitat von @webglider:
Aber so wie ich das sehe, wir immer nur der letzte Teil des Pfades ermittelt, oder?

kundeX ist leider nicht generell der letzte Teil des Pfades, was nun?

Es kann auch so aussehen: c:\tool\kunde1\batch\script.bat. Wie komme ich da an kunde1?

Vielleicht könntest Du jetzt wieder den Kreis schließen und zu dieser %MY-KRAMS%-Variable zurückfinden.
Gehen von diesem sagenumwobenen Verzeichnis eventuell alle "kundeXXX"-Unterverzeichnisse ab?
[/Edit]
Mitglied: webglider
webglider 28.04.2009 um 19:26:45 Uhr
Goto Top
Danke euch beiden erst einmal für die Hilfe.

Aber so wie ich das sehe, wir immer nur der letzte Teil des Pfades ermittelt, oder?

kundeX ist leider nicht generell der letzte Teil des Pfades, was nun?

Es kann auch so aussehen: c:\tool\kunde1\batch\script.bat. Wie komme ich da an kunde1?
Mitglied: 77559
77559 28.04.2009 um 19:36:47 Uhr
Goto Top
Zitat von @webglider:
Es kann auch so aussehen: c:\tool\kunde1\batch\script.bat. Wie komme ich da an kunde1?

Wieder einmal das Problem sich ändernder Anforderungen

Du schriebst der Teil vor dem Kunde ist Variabel, jetzt auch der Teil danach - das kann nicht funktionieren.

Wenn DU dir nicht vorher ein Konzept überlegst sind unsere Beiträge sinnlos und das schafft Dir keine Freunde. face-sad

Gruß
LotPings
Mitglied: miniversum
miniversum 28.04.2009 um 19:36:55 Uhr
Goto Top
Schau ob du Bibers Übungsbatch veerstanden hast ist das recht leicht an diesen teil des Verzeichnisses zu kommen.
Aber wenn du es universell willst solltest du uns schon sagen woran die Batch erkennen soll welcher der Teile den Kunde ist.
im Beispiel
c:\tool\kunde1\batch\script.bat
könnte der Kunde ja entwerder tool, kunde1 oder batch heißen. Gibt es also eine einheitliche kennung oder wilsl tdu nur ohne jedennutzen wissen wie man diese teile bekommt?
Mitglied: webglider
webglider 29.04.2009 um 13:37:39 Uhr
Goto Top
Zitat von @miniversum:
Gibt es also eine einheitliche kennung oder willst du
nur ohne jeden nutzen wissen wie man diese teile bekommt?

Ja, es gibt eine eindeutige Kennung. Im Verzeichnis %MY-PATH% gibt es für jeden Kunden ein Unterverzeichnis:

%MY-PATH%\kunde1
%MY-PATH%\kunde2
%MY-PATH%\kunde3

Ich möchte also prüfen, ob es eine Übereinstimmung im aktuellen Pfad des Skriptes mit einem der Unterverzeichnisse unterhalb von %MY-PATH% gibt.

Pseudo-Code:

if teilDesSkriptPfades = einesDerUnterverzeichnisseVonMY-PATH then KUNDE = teilDesSkriptPfades

Nachvollziehbar?
Mitglied: miniversum
miniversum 29.04.2009 um 18:35:22 Uhr
Goto Top
Dan versuchs mal damit:
FOR /F "delims=" %%i in (dir /AD /B "%MY-PATH%") do echo %~p0|find "%%i" >NUL 2>NUL && set Kunde=%%i  
echo %Kunde%
Mitglied: 77559
77559 29.04.2009 um 18:44:02 Uhr
Goto Top
Zitat von @miniversum:
Dan versuchs mal damit:
FOR /F "delims=" %%i in (dir /AD /B "%MY-PATH%") do echo %~p0|find "%%i" >NUL 2>NUL && set Kunde=%%i  
echo %Kunde%

Besser nur ~nx von %%%i nehmen und der dir müsste mit ' ' eingefasst werden.
FOR /F "delims=" %%i in ('dir /AD /B "%MY-PATH%" ') do echo %~p0|find "%%~nxi" >NUL 2>NUL && set Kunde=%%~nxi  
echo Kunde ist:%Kunde%

Gruß

Edit verschachtelte Code und Red will er nicht Mist, wieder rausgenommen[/EDIT]
Mitglied: miniversum
miniversum 29.04.2009 um 19:44:19 Uhr
Goto Top
Die '' hatte ich vergessen. Danke.
Ob isch nx oder direkt %%i nehme ist egal weil ja, nach siener beschribung, die Verzeichnisnamen in %MY-PATH% sowieso die Kunden enthalten. direkt also. Es bringt also keinen vorteil.
Mitglied: bastla
bastla 29.04.2009 um 19:50:29 Uhr
Goto Top
Hallo @all!

Der Genauigkeit wegen sollte vielleicht ein Vergleich unter Verwendung der vor und nach dem Kundennamen erforderlichen Backslashes erfolgen, also etwa:
FOR /F "delims=" %%i in ('dir /AD /B "%MY-PATH%" ') do echo %~p0|findstr /i /c:"\\%%~nxi\\" >NUL 2>NUL && set "Kunde=%%~nxi"
Grüße
bastla
Mitglied: webglider
webglider 29.04.2009 um 20:06:44 Uhr
Goto Top
Zitat von @77559:
> Zitat von @miniversum:
> ----
> Dan versuchs mal damit:
FOR /F "delims=" %%i in (dir /AD /B  
> "%MY-PATH%") do echo %~p0|find "%%i" >NUL  
> 2>NUL && set Kunde=%%i
> echo %Kunde%

Besser nur ~nx von %%%i nehmen und der dir müsste mit '
' eingefasst werden.
FOR /F "delims=" %%i in ('dir /AD /B  
> "%MY-PATH%" ') do echo %~p0|find "%%~nxi"  
> >NUL 2>NUL && set Kunde=%%~nxi
> echo Kunde ist:%Kunde%

Gruß

Edit verschachtelte Code und Red will er nicht Mist, wieder
rausgenommen[/EDIT]


Super, danke euch allen. Mit dieser Variante ist mein Problem gelöst. Nächstes mal versuche ich meine Anforderungen gleich am Anfang genauer zu formulieren.

Danke nochmal.