Windows Batch files: what is variable expansion, and what does EnableDelayedExpansion mean?

  • Variable expansion means replace a variable enclosed in % or ! by its value.
  • The %normal% expansion happen just once, before a line is executed. This means that a %variable% expansion have the same value no matters if the line is executed several times (like in a for command).
  • The !delayed! expansion is performed each time that the line is executed.

See this example:

@echo off
setlocal EnableDelayedExpansion
set "var=Original"
set "var=New" & echo Normal: "%var%", Delayed: "!var!"

Output:

Normal: "Original", Delayed: "New"

Another one:

@echo off
setlocal EnableDelayedExpansion
set "var1=Normal"
set "var2=Delayed"
for /L %%i in (1,1,10) do (
   set "var1=%var1% %%i"
   set "var2=!var2! %%i"
)
echo Normal:  "%var1%"
echo Delayed: "%var2%"

Output:

Normal:  "Normal 10"
Delayed: "Delayed 1 2 3 4 5 6 7 8 9 10"

Normal expansion is not necessarily a disadvantage, but depends on the specific situation it is used. For example, in any other programming languages, to exchange the value of two variables you need the aid of a third one, but in Batch it can be done in just one line:

set "var1=%var2%" & set "var2=%var1%"

In batch variables are expanded by enclosing them in percent signs.

set myVariable=Hello world
echo %myVariable%

That means variable expansion.

Compared to other programming languages, batch don't really work with variables.
Normally it works only with the expansion of them.
It works like the macro expansion of C/C++.

So there doesn't exist a string length function to get the length of a variable,
but you can write a function that counts the characters of text.

Explanation of setLocal EnableDelayedExpansion
The normal percent expansion has two disadvantages.

The expansion happens in the moment of the parsing of a line or a block enclosed with parenthesis, not when the block is executed.

Lets see this sample

set var=one

set var=two & echo %var%
echo %var%

The output will be

one
two

As the echo %var% will be expand before the set var=two will be executed. This can get problematic in FOR loops.

And the second disadvantage is that the batch parser will parse the expanded result of the variable.

set var=cat^&dog
echo %var%

var
Unknown command "dog"

But the percent expansion exists since the beginning of MS-Dos (1920 or so).

The DelayedExpansion adds a new expansion character, the exclamation mark !.

But you have to active it first to use it with setlocal EnableDelayedExpansion, this is for compatibility reasons to old programs.

setlocal EnableDelayedExpansion
set var=one
set var=two & echo !var!
set var=cat^&dog
echo !var!

two
cat&dog

So this solves both problems of the percent expansion.

Delayed Expansion on the command line
You can't enable it by setlocal EnableDelayedExpansion, on the command line it has no effect at all.
But you can use cmd /v:on

set "var=Cat & dog" & cmd /V:on /c echo !var!