You are not the first, who fell into the famous “delayed expansion trap” (and you won’t be the last).
You need delayed expansion if you want to use a variable, that you changed in the same block (a block is a series of commands within parentheses
Delayed variables are referenced with
!var! instead of
Reason is the way,
cmd parses the code. A complete line or block is parsed at once, replacing normal variables with their value at parse time. Delayed variables are evaluated at runtime.
Two simple batch files to demonstrate:
setlocal EnableDelayedExpansion set "var=hello" if 1==1 ( set "var=world" echo %var% !var! )
setlocal EnableDelayedExpansion for /L %%i in (1,1,5) do ( echo %random% !random! )
Note: A line is also treated as a block:
set "var=old" set "var=new" & echo %var%
With delayed expansion:
setlocal EnableDelayedExpansion set "var=old" set "var=new" & echo !var!
Delayed expansion is per default turned off at the command prompt. If you really need it, you can do:
cmd /V:ON /C "set "var=hello" & echo !var!"
Also there is a way to do the same without delayed expansion (but
call costs some time, so it’s slower, but if for some reason you can’t / don’t want to use delayed expansion, it’s an alternative):
setlocal DISabledelayedexpansion for /L %%i in (1 1 5) do ( call echo %random% %%random%% )
Both methods can also be used to display array-like variables:
(This is often asked like “variable which contains another variable” or “nested variables”)
Here is a collection for using such array-like variables in different situations:
With delayed expansion:
setlocal ENableDelayedExpansion set "num=4" set "var[%num%]=HELLO" echo plain delayed: !var[%num%]! for /L %%i in (4 1 4) do ( echo for delayed: !var[%%i]! set a=%%i call echo for delayed with variable: %%var[!a!]%% )
without delayed expansion:
setlocal DISableDelayedExpansion set "num=4" set "var[%num%]=HELLO" call echo plain called: %%var[%num%]%% for /L %%i in (4 1 4) do ( call echo FOR called: %%var[%%i]%% set a=%%i call echo FOR called with variable: %%var[%a%]%% )
setlocal has no effect outside of batchfiles, so
delayedexpansion works only:
- In batch files
- When the cmd was started with delayed expansion enabled (
cmd /V:ON) (by default, the cmd runs with delayed expansion disabled)
(Follow the links, when you are interested in the technical background or even the advanced technical stuff)