As variáveis de ambiente nos arquivos em lote são expandidas quando uma linha é analisada. No caso de blocos delimitados por parênteses (como o seu if defined
), o bloco inteiro conta como uma "linha" ou comando.
Isso significa que todas as ocorrências de% FOO% são substituídas por seus valores antes que o bloco seja executado. No seu caso sem nada, pois a variável ainda não tem um valor.
Para resolver isso, você pode ativar a expansão atrasada :
setlocal enabledelayedexpansion
A expansão atrasada faz com que variáveis delimitadas por pontos de exclamação ( !
) sejam avaliadas na execução, em vez de analisar, o que garantirá o comportamento correto no seu caso:
if not defined BAR (
set FOO=1
echo Foo: !FOO!
)
help set
detalha isso também:
Finalmente, foi adicionado suporte para expansão de variável de ambiente atrasada. Esse suporte está sempre desativado por padrão, mas pode ser ativado / desativado através da /V
opção de linha de comando para CMD.EXE
. VejoCMD /?
A expansão de variável de ambiente atrasada é útil para contornar as limitações da expansão atual, que ocorre quando uma linha de texto é lida, não quando é executada. O exemplo a seguir demonstra o problema com a expansão imediata de variáveis:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo If you see this, it worked
)
nunca exibiria a mensagem, pois as instruções %VAR%
em ambas IF
são substituídas quando a primeira instrução IF é lida, uma vez que inclui logicamente o corpo da IF
, que é uma instrução composta. Portanto, o IF dentro da instrução composta está realmente comparando "antes" com "depois", o que nunca será igual. Da mesma forma, o exemplo a seguir não funcionará conforme o esperado:
set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%
na medida em que não criará uma lista de arquivos no diretório atual, mas apenas definirá a LIST
variável para o último arquivo encontrado. Novamente, isso ocorre porque o %LIST%
é expandido apenas uma vez quando a FOR
instrução é lida e, nesse momento, a LIST
variável está vazia. Portanto, o loop FOR real que estamos executando é:
for %i in (*) do set LIST= %i
que continua definindo LIST
o último arquivo encontrado.
A expansão de variável de ambiente atrasada permite que você use um caractere diferente (o ponto de exclamação) para expandir as variáveis de ambiente no tempo de execução. Se a expansão variável atrasada estiver ativada, os exemplos acima podem ser escritos da seguinte maneira para funcionar como pretendido:
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%
!
, use^^^!
(escape duas vezes). Caso contrário, o recurso "expansão atrasada" o consumirá.