我有一个批处理文件,它通过for循环中的SET初始化变量,对于磁盘上的一组文件:
for %%f in (%MYTARGETDIR%\*config.xml) do (
SET TMPFILE=%%F.tmp
echo In loop %TMPFILE%
)
echo End loop %TMPFILE%
当我在一个全新的命令shell(没有定义TMPFILE)中运行它时,In循环回显为空,但结束循环回显不是。
当我第二次运行时,它已经设置并输出其值,忽略该设置直到循环关闭。
为什么会这样,以及解决方法是什么?
答案 0 :(得分:21)
对于记录,更正后的脚本如下所示:
setlocal ENABLEDELAYEDEXPANSION
for %%f in (%MYTARGETDIR%\*config.xml) do (
SET TMPFILE=%%F.tmp
echo In loop !TMPFILE!
)
echo End loop %TMPFILE%
感谢克里斯的帮助。
答案 1 :(得分:16)
因为当命令 read 时,环境变量被替换。对于以下命令:
for %%f in (%mytargetdir%\*config.xml) do (
set tmpfile=%%f.tmp
echo In loop %tmpfile%
)
在执行之前读取并替换整个命令(从for
到右括号)。
您需要使用延迟扩展,例如:
@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
启用延迟展开后,"%"
标记仍然可以像以前一样运行,但您可以使用"!"
标记执行延迟扩展。
答案 2 :(得分:9)
那是因为()块只被解析一次,它在运行循环之前替换了%TMPFILE%。
答案 3 :(得分:6)
您也可以使用CALL SET代替延迟扩展。
答案 4 :(得分:2)
通常,我使用/ e:on和/ v:on开关调用CMD.EXE以启用命令扩展和延迟变量扩展。然后编码我使用的任何批处理脚本以检查延迟变量扩展是否已打开。
这是我第一次听说SETLOCAL接受争论。我用SETLOCAL /检查了?果然!对我来说,这是一个时间和代码保护程序。
但是,我注意到在SETLOCAL识别ENABLEDELAYEDEXPANSION选项之前,必须在CMD.EXE中启用命令扩展。这是来自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.
谢谢你们这个有价值的答案。