Переменные среды в пакетных файлах раскрываются при разборе строки. В случае блоков, разделенных круглыми скобками (как ваш if defined
), весь блок считается «строкой» или командой.
Это означает, что все вхождения% FOO% заменяются своими значениями до запуска блока. В вашем случае ни с чем, так как переменная еще не имеет значения.
Чтобы решить эту проблему, вы можете включить отложенное расширение :
setlocal enabledelayedexpansion
Отложенное расширение приводит к тому, что переменные, разделенные восклицательными знаками ( !
), оцениваются при выполнении вместо анализа, что обеспечит правильное поведение в вашем случае:
if not defined BAR (
set FOO=1
echo Foo: !FOO!
)
help set
Подробности это тоже:
Наконец, добавлена поддержка отложенного расширения переменных среды. Эта поддержка всегда отключена по умолчанию, но ее можно включить / отключить с помощью /V
переключателя командной строки CMD.EXE
. ВидетьCMD /?
Задержка раскрытия переменных среды полезна для преодоления ограничений текущего раскрытия, которое происходит при чтении строки текста, а не при ее выполнении. В следующем примере демонстрируется проблема с немедленным расширением переменной:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo If you see this, it worked
)
никогда не будет отображать сообщение, так как %VAR%
в обоих IF
операторах подставляется при чтении первого оператора IF, так как он логически включает в себя тело IF
оператора, который является составным оператором. Таким образом, IF внутри составного оператора действительно сравнивает «до» с «после», которое никогда не будет равным. Аналогично, следующий пример не будет работать должным образом:
set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%
в том смысле, что он не будет создавать список файлов в текущем каталоге, а просто установит LIST
переменную для последнего найденного файла. Опять же, это происходит потому, %LIST%
что, когда FOR
оператор читается, он раскрывается только один раз , и в это время LIST
переменная пуста. Итак, фактический цикл FOR, который мы выполняем:
for %i in (*) do set LIST= %i
который просто сохраняет настройки LIST
до последнего найденного файла.
Задержка раскрытия переменных среды позволяет использовать другой символ (восклицательный знак) для раскрытия переменных среды во время выполнения. Если расширение отложенной переменной включено, приведенные выше примеры могут быть написаны следующим образом, чтобы работать как задумано:
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%
!
, используйте^^^!
(избегайте дважды). В противном случае функция «отложенного расширения» сожрет ее.