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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 06:11:30  来源:igfitidea点击:

Batch file variables initialized in a for loop

windowsbatch-file

提问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 forto 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 George V. Reilly

You can also use CALL SETinstead of delayed expansion.

您还可以使用CALL SET代替延迟扩展。

回答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.

感谢两位提供这个宝贵的答案。