Finalmente, foi adicionado o suporte à expansão de variáveis de ambiente atrasada. Esse suporte está sempre desativado por ...

Finalmente, foi adicionado o suporte à expansão de variáveis de ambiente
atrasada. Esse suporte está sempre desativado por padrão, mas pode ser
ativado/desativado através da opção da linha de comando /V do CMD.EXE.
Consulte CMD /?

A expansão de variáveis de ambiente atrasada é útil para contornar
as limitações da expansão atual que ocorre quando uma linha
de texto é lida, e não quando é executada. O exemplo a seguir
demonstra o problema com a expansão de variável imediata:

    set VAR=antes
    if "%%VAR%%" == "antes" (
        set VAR=depois
        if "%%VAR%%" == "depois" @echo Se você ler isto, terá funcionado
    )

nunca exibiria a mensagem, já que %%VAR%% em AMBAS as instruções IF
é substituído quando a primeira instrução IF é lida, pois inclui
logicamente o corpo do IF, que é uma instrução composta. Portanto, o
IF dentro da instrução composta está realmente comparando "antes" com
"depois", que nunca será igual. Da mesma forma, o exemplo a seguir
não funcionará como esperado:

    set LIST=
    for %%i in (*) do set LIST=%%LIST%% %%i
    echo %%LIST%%

porque NÃO criará uma lista de arquivos na pasta atual mas,
em vez disso, apenas definirá a variável LIST como o último arquivo encontrado.
Novamente, isso ocorre porque a %%LIST%% é expandida apenas uma vez
quando a instrução FOR é lida, e nesse momento a variável LIST está vazia.
Portanto, o loop FOR que está de fato sendo executado é:

    for %%i in (*) do set LIST= %%i

que apenas continua definindo LIST como o último arquivo encontrado.

A expansão de variáveis de ambiente atrasada permite usar um caractere
diferente (o ponto de exclamação) para expandir variáveis de ambiente no
tempo de execução. Se a expansão de variáveis atrasada estiver ativada,
os exemplos acima poderão ser escritos da seguinte forma para funcionar
como o desejado:

    set VAR=antes
    if "%%VAR%%" == "antes" (
        set VAR=depois
        if "!VAR!" == "depois" @echo Se você ler isto, terá funcionado
    )

    set LIST=
    for %%i in (*) do set LIST=!LIST! %%i
    echo %%LIST%%