@echo off
if 1 == 1 (echo yes) else (echo no)
echo Writing a long ^
text here
if 1 == 1 (
echo yes
) else (
echo no
)
Why should one know? As said already, it's an interpreter we use, and it's applying some string replacements.
set example=1
if %example% == 1 (
set example=2
echo %example%
)
REM result: 1
REM expected: 2
In the first line, variable
example is set to 1. In the next "line", containing
IF up to the closing bracket, each occurance of
%example% is replaced by the value set at that time, which is 1. That's why we almost always use
Delayed Expansion. I will not further discuss that feature here; however, it might bring another headache in some (very advanced) cases:
setlocal EnableDelayedExpansion
set pwd=#^!pwd#
echo !pwd! %pwd%
set pwd=#^^^!pwd#
echo !pwd! %pwd%
Try it, and try to spot the exclamation mark ...
for /F "tokens=*" %%F in ('dir /a:-d . /s/b ^| find "\temp\"') do del /f %%F
The pipe character needed escaping, because it is used for piping the output of one command to the input of another. If not escaped,
cmd.exe would try to parse it when reading the complete line, which leads to a syntax error because of incomplete
FOR.
@echo off
set Var=Value 1
if 1==1 (
echo Var when entering the block: %Var%; setting it to "Value 2" now ...
set Var=Value 2
goto SomeLabel
:SomeLabel
echo Var is now: %Var%
)
This will output Var as being 2, while without
GOTO it results in 1, the value set before the block. This is because
cmd.exe will reinterpret the code after it executes a
GOTO. This is only a showcase, of course, noone would ever come to the conclusion having to use a goto in a block?!
(echo Start
for /L %%L in (1,1,100) do echo %%L
echo End
REM --- Missing closing ")" here
Will not echo anything - because the line is never ended because of the missing ")", and the command is never executed ...
for %F in (*) do ^
echo %%F
will give you errors that the command " " could not be found.
if 1 == 1 echo yes & echo another yes
This line will echo both commands. I.e. the line after
IF is handled as one command. You could expect, as
& is the command separator, that the
IF is evaluated up to the ampersand, and after this is starting a new command. Wrong!
for %F in (*) do @echo %F > output.txt
for %F in (*) do @echo %F >> output.txt
(for %F in (*) do @echo %F) > output.txt
Line 1 will write the last result into
output.txt. You could expect that the stdout redirection into a file (
> output.txt) would apply to the
FOR, but it's not, it is applied to the command (
ECHO). And that is meaning that the file is overwritten in each go of the
FOR loop. This also means that the file is opened and closed multiple times, which is a performance issue, so even if you use the append (
>>) redirector like shown in line 2 it would be bad practice.
>> output.txt echo yes
>> output.txt if 1 == 1 echo This is a syntax error
>> output.txt (if 1 == 1 echo yes, three)
>> output.txt dir c:\* | findstr MyFiles
>> output.txt (dir c:\* | findstr MyFiles)
The first and third line actually work, the echoed text is appended to
output.txt. After understanding the first line, the second seems to be logically correct - but instead, a syntax error is generated, stating
IF is not expected at that position.
dir c:\* | >> output.txt findstr MyFiles
@echo off
call :genscript > script.cmd
call script.cmd
exit /b
:genscript
echo @echo off
echo dir
exit /b
call :genscript | findstr dir
we get the same error as if we would try to use that call on commandline. I did not find any workaround to get this running yet.
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (14)
Commented:
I'm curious if you can turn off Delayed Expansion (if it is on by default) with endlocal:
endlocal
call :label Now you see it!
This will work if setlocal enabledelayedexpansion is explicitly set earlier in the script, but I don't know if it will work if expansion is on by default.
Author
Commented:Commented:
Anyway, good article.
Author
Commented:Commented:
View More