windows 在 for 循环中初始化的批处理文件变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/691047/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Batch file variables initialized in a for loop
提问by theschmitzer
I have a batch file which initializes variables via SET inside a for loop, for a set of files on disk:
我有一个批处理文件,它通过 for 循环内的 SET 为磁盘上的一组文件初始化变量:
for %%f in (%MYTARGETDIR%\*config.xml) do (
SET TMPFILE=%%F.tmp
echo In loop %TMPFILE%
)
echo End loop %TMPFILE%
when I run this in a brand new command shell (without TMPFILE defined) the In loop echo is empty, but the end loop echo is not.
当我在全新的命令外壳(未定义 TMPFILE)中运行它时,循环内回声为空,但结束循环回声不是。
When I run a second time, its already set, and outputs its value, ignoring the set until the loop closes.
当我第二次运行时,它已经设置并输出它的值,在循环关闭之前忽略该设置。
Ideas why this is, and what the workaround is?
想法为什么会这样,以及解决方法是什么?
采纳答案by laktak
That's because the ( ) block is parsed only once, it substitutes %TMPFILE% before it runs your loop.
那是因为 ( ) 块只被解析一次,它在运行循环之前替换 %TMPFILE% 。
回答by theschmitzer
For the record, the corrected script looks like this:
作为记录,更正后的脚本如下所示:
setlocal ENABLEDELAYEDEXPANSION
for %%f in (%MYTARGETDIR%\*config.xml) do (
SET TMPFILE=%%F.tmp
echo In loop !TMPFILE!
)
echo End loop %TMPFILE%
Thanks chris for your help.
感谢克里斯的帮助。
回答by paxdiablo
It because environment variables are substituted when the command is read. For the following command:
这是因为在读取命令时会替换环境变量。对于以下命令:
for %%f in (%mytargetdir%\*config.xml) do (
set tmpfile=%%f.tmp
echo In loop %tmpfile%
)
the entire command (from for
to the closing parenthesis) is read and substituted before execution.
for
在执行之前读取并替换整个命令(从到右括号)。
You need to use delayed expansion, such as with:
您需要使用延迟扩展,例如:
@echo off
setlocal enableextensions enabledelayedexpansion
set full=/u01/users/pax
:loop1
if not "!full:~-1!" == "/" (
set full2=!full:~-1!!full2!
set full=!full:~,-1!
goto :loop1
)
echo !full!
endlocal
When you enable delayed expansion, the "%"
markers still act as before but you can use the "!"
markers to do the delayed expansion.
当您启用延迟扩展时,"%"
标记仍然像以前一样工作,但您可以使用"!"
标记进行延迟扩展。
回答by Garry Offord
Normally, I invoke CMD.EXE with the /e:on and /v:on switches to enable command extensions and delayed variable expansion. Then any batch scripts that I use are coded to check that delayed variable expansion is turned on.
通常,我使用 /e:on 和 /v:on 开关调用 CMD.EXE 以启用命令扩展和延迟变量扩展。然后我使用的任何批处理脚本都被编码来检查延迟变量扩展是否打开。
This is the first time I have heard of SETLOCAL taking arguments. I checked with SETLOCAL /? and sure enough! This is such a time and code saver for me.
这是我第一次听说 SETLOCAL 接受参数。我用 SETLOCAL /? 果然!这对我来说节省了时间和代码。
However, I did notice that command extensions must be enabled in CMD.EXE before SETLOCAL will recognize the ENABLEDELAYEDEXPANSION option. This is from the output of SETLOCAL /?
但是,我确实注意到必须在 CMD.EXE 中启用命令扩展,然后 SETLOCAL 才能识别 ENABLEDELAYEDEXPANSION 选项。这是来自 SETLOCAL /?
If Command Extensions are enabled SETLOCAL changes as follows:
SETLOCAL batch command now accepts optional arguments:
ENABLEEXTENSIONS / DISABLEEXTENSIONS
enable or disable command processor extensions. These
arguments takes precedence over the CMD /E:ON or /E:OFF
switches. See CMD /? for details.
ENABLEDELAYEDEXPANSION / DISABLEDELAYEDEXPANSION
enable or disable delayed environment variable
expansion. These arguments takes precedence over the CMD
/V:ON or /V:OFF switches. See CMD /? for details.
Thank you both for this valuable answer.
感谢两位提供这个宝贵的答案。