Umgebungsvariablen in Batch-Dateien werden beim Parsen einer Zeile expandiert. Bei Blöcken, die durch Klammern begrenzt sind (wie Ihr if defined
), zählt der gesamte Block als eine “Zeile” oder ein Befehl.
Das bedeutet, dass alle Vorkommen von %FOO% durch ihre Werte ersetzt werden, bevor der Block ausgeführt wird. In Ihrem Fall durch nichts, da die Variable noch keinen Wert hat.
Um dies zu lösen, können Sie die verzögerte Expansion aktivieren:
setlocal enabledelayedexpansion
Die verzögerte Expansion bewirkt, dass Variablen, die durch Ausrufezeichen (!
) begrenzt sind, bei der Ausführung ausgewertet werden, anstatt geparst zu werden, was in Ihrem Fall das richtige Verhalten sicherstellt:
if not defined BAR (
set FOO=1
echo Foo: !FOO!
)
help set
Details dazu:
Schließlich wurde die Unterstützung für verzögerte Expansion von Umgebungsvariablen hinzugefügt. Diese Unterstützung ist standardmäßig immer deaktiviert, kann aber über den Befehlszeilenschalter /V
auf CMD.EXE
aktiviert/deaktiviert werden. Siehe CMD /?
Die verzögerte Umgebungsvariablenexpansion ist nützlich, um die Einschränkungen der aktuellen Expansion zu umgehen, die beim Lesen einer Textzeile und nicht bei deren Ausführung erfolgt. Das folgende Beispiel demonstriert das Problem mit der sofortigen Variablenexpansion:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo If you see this, it worked
)
würde niemals die Meldung anzeigen, da das %VAR%
in beiden IF
-Anweisungen ersetzt wird, wenn die erste IF-Anweisung gelesen wird, da sie logischerweise den Körper des IF
enthält, der eine zusammengesetzte Anweisung ist. Das IF innerhalb der zusammengesetzten Anweisung vergleicht also wirklich “vorher” mit “nachher”, was niemals gleich sein wird. In ähnlicher Weise wird das folgende Beispiel nicht wie erwartet funktionieren:
set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%
, da es nicht eine Liste der Dateien im aktuellen Verzeichnis aufbaut, sondern stattdessen nur die Variable LIST
auf die letzte gefundene Datei setzt. Das liegt wiederum daran, dass die Variable %LIST%
nur einmal expandiert wird, wenn die Anweisung FOR
gelesen wird, und zu diesem Zeitpunkt ist die Variable LIST
leer. Die tatsächliche FOR-Schleife, die wir ausführen, lautet also:
for %i in (*) do set LIST= %i
, was einfach LIST
auf die zuletzt gefundene Datei setzt.
Die verzögerte Umgebungsvariablenexpansion ermöglicht es Ihnen, ein anderes Zeichen (das Ausrufezeichen) zu verwenden, um Umgebungsvariablen zur Ausführungszeit zu expandieren. Wenn die verzögerte Variablenexpansion aktiviert ist, könnten die obigen Beispiele wie folgt geschrieben werden, um wie vorgesehen zu funktionieren:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" @echo If you see this, it worked
)
set LIST=
for %i in (*) do set LIST=!LIST! %i
echo %LIST%