@Ed - Not quite the full story. :;
!Text! is not getting expanded within the IN() clause CMD.EXE session. It is getting expanded by the parent batch within the DO clause. Disable delayed expansion and you can see what I mean.
Code: Select all
@echo off
SetLocal EnableDelayedExpansion
Set "Text=/?"
For /F "delims=" %%# in (
'SetLocal EnableDelayedExpansion ^&Echo(^^!Text^^!'
) do (
setlocal disableDelayedExpansion
Echo(%%#
endlocal
)
result
The problem is that the IN() clause is executed under a command line context, not a batch file context. SETLOCAL does not work under a command line context.
To get delayed expansion within the IN() clause requires using CMD /V:ON. It is easiest if quotes are used. But it is also possible without quotes.
Code: Select all
@echo off
SetLocal EnableDelayedExpansion
Set "Text=/?"
For /F "delims=" %%# in (
'cmd /v:on /c "echo(^!Text^!"'
) do (
setlocal disableDelayedExpansion
Echo(%%#
endlocal
)
echo(
For /F "delims=" %%# in (
'cmd /v:on /c echo(^^^!Text^^^!'
) do (
setlocal disableDelayedExpansion
Echo(%%#
endlocal
)
exit /b
But, how to prove that the expansion is happening within the IN() clause CMD session, and not within the parent batch? Here I provide 2 proofs within one set of examples.
I'm going to use !ERRORLEVEL! instead of !Text!. I want to echo the ERRORLEVEL that results from a command that executed within the IN() clause. I'll use a command (HELP HELP) that generates an error, and print the ERRORLEVEL both before and after.
The other proof is the use of !CMDCMDLINE! to show the command line that was used to launch the currently executing CMD.EXE session. This gets very confusing because there are actually two CMD sessions in the example. One is created implicitly by the FOR /F command, and the second is created explicitly by our command. This also makes the escape rules horrificly complicated.
My first test uses quotes around everything. I show both CMD contexts.
My 2nd and 3rd tests require more escaping, so I simplified by dropping the printout of the initial CMD context.
But my 4th example attempts to put it all together, showing both contexts without any quotes, and it gives really screwy results. The CMD /V:ON... command gets executed twice
Edit - removed extra ^ from escaped (not quoted) delayed expansion: ^^^!var^^^! --> ^^!var^^!
Edit 2 - removed some additional extra ^: ^^^= --> ^= and ^^^^^^^& --> ^^^^^& and ^^^^^^^> --> ^^^^^>Code: Select all
@echo off
setLocal enableDelayedExpansion
for /f "delims=" %%# in (
'"echo 1st cmdLine: %%cmdcmdline%%&cmd /v:on /c echo 2nd cmdLine: ^!cmdcmdline^!^^&echo err=^!errorlevel^!^^&^^>nul help help^^&echo err=^!errorlevel^!"'
) do (
setlocal disableDelayedExpansion
echo test1: %%#
endlocal
)
echo(
for /f "delims=" %%# in (
'cmd /v:on /c "echo 2nd cmdLine: ^!cmdcmdline^!&echo err=^!errorlevel^!&>nul help help&echo err=^!errorlevel^!"'
) do (
setlocal disableDelayedExpansion
echo test2: %%#
endlocal
)
echo(
for /f "delims=" %%# in (
'cmd /v:on /c echo 2nd cmdLine: ^^!cmdcmdline^^!^^^^^&echo err^=^^!errorlevel^^!^^^^^&^^^^^>nul help help^^^^^&echo err^=^^!errorlevel^^!'
) do (
setlocal disableDelayedExpansion
echo test3: %%#
endlocal
)
echo(
for /f "delims=" %%# in (
'echo 1st cmdLine: %%cmdcmdline%%^&cmd /v:on /c echo 2nd cmdLine: ^^!cmdcmdline^^!^^^^^&echo err^=^^!errorlevel^^!^^^^^&^^^^^>nul help help^^^^^&echo err^=^^!errorlevel^^!'
) do (
setlocal disableDelayedExpansion
echo test4: %%#
endlocal
)
results
Code: Select all
test1: 1st cmdLine: C:\Windows\system32\cmd.exe /c "echo 1st cmdLine: %cmdcmdline%&cmd /v:on /c echo 2nd cmdLine: !cmdcmdline!^&echo err=!errorlevel!^&^>nul help help^&echo err=!errorlevel!"
test1: 2nd cmdLine: cmd /v:on /c echo 2nd cmdLine: !cmdcmdline!&echo err=!errorlevel!&>nul help help&echo err=!errorlevel!
test1: err=0
test1: err=1
test2: 2nd cmdLine: cmd /v:on /c "echo 2nd cmdLine: !cmdcmdline!&echo err=!errorlevel!&>nul help help&echo err=!errorlevel!"
test2: err=0
test2: err=1
test3: 2nd cmdLine: cmd /v:on /c echo 2nd cmdLine: !cmdcmdline!&echo err=!errorlevel!&>nul help help&echo err=!errorlevel!
test3: err=0
test3: err=1
test4: 1st cmdLine: C:\Windows\system32\cmd.exe /c echo 1st cmdLine: %cmdcmdline%
test4: 2nd cmdLine: cmd /v:on /c echo 2nd cmdLine: !cmdcmdline!&echo err=!errorlevel!&>nul help help&echo err=!errorlevel!
test4: err=0
test4: err=1
test4: 2nd cmdLine: cmd /v:on /c echo 2nd cmdLine: !cmdcmdline!&echo err=!errorlevel!&>nul help help&echo err=!errorlevel!
test4: err=0
test4: err=1
Dave Benham