Windows command processor replaces all occurrences of %variable%
within a command block starting with (
and ending with matching )
by current value of referenced environment variable before the command is executed using the command block. See How does the Windows Command Interpreter (CMD.EXE) parse scripts? This command block handling by cmd.exe
can be seen by running the batch file from within a command prompt window instead of double clicking on the batch file with @echo off
removed or modified to @echo ON
or commented out temporarily until the batch file is working as expected.
The help output on running set /?
in a command prompt window explains on an IF and a FOR example when and how to use delayed expansion which is the preferred method to access an environment variable value within a command block being defined or modified in same command block.
The other solution is referencing the environment variable using the syntax %%variable%%
and using command CALL to force a double parsing of this command line by cmd.exe
. In this case %%
is modified on parsing entire command block to %
on both sides of the referenced environment variable and later on execution of command CALL the remaining %variable%
is parsed once again and substituted by current value of the referenced variable.
In posted batch code the environment variable str
is not defined above FOR command line with the command block. For that reason echo %str% >> names.txt
is on parsing the entire command block modified by cmd.exe
to echo >> names.txt
before FOR is executed at all and so ECHO just outputs three times the current status.
Also the command line call set str=%%str:Name=%word%%%
does not work because of word
is not defined before FOR command line with the command block and therefore %word%
is substituted already by nothing resulting in the command line call set str=%str:Name=%
being finally executed three times on loop execution.
The next error is usage of FOR option /L
for this loop. The help output on running for /?
in a command prompt window explains for for /L
:
FOR /L %variable IN (start,step,end) DO command [command-parameters]
The set is a sequence of numbers from start to end, by step amount.
So (1,1,5) would generate the sequence 1 2 3 4 5 and (5,-1,1) would
generate the sequence (5 4 3 2 1)
It should be clear after reading this help that /L
is not the right option for this task.
The next mistake is that string substitutions done with command SET or directly by cmd.exe
on parsing the command line are always applied case-insensitive. The string assigned to environment variable str
contains name
and Name
which are both replaced on string substitution. That is not really wanted here.
Then there is a big difference on using set variable="value"
or on using set "variable=value"
. The latter is the better as explained in detail in answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line?
Finally the space character left to redirection operator >>
is also output by command ECHO resulting in a trailing space in the file. Therefore the redirection operator >>
should not be separated by a space from string to write into the file.
First working code for the example uses delayed environment variable expansion:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
del names.txt 2>nul
set "str=My name is #name#"
for %%I in (Veronica, Nils, Mike, Tom) do echo !str:#name#=%%~I!>>names.txt
endlocal
Second working code for the example uses the CALL trick:
@echo off
del names.txt 2>nul
set "str=My name is #name#"
for %%I in (Veronica, Nils, Mike, Tom) do call echo %%str:#name#=%%~I%%>>names.txt
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
del /?
echo /?
endlocal /?
for /?
setlocal /?
set /?
See also the Microsoft article about Using command redirection operators.