我正在尝试做一个简单的批处理(它不是全部,但这是导致一切失败的部分)
@echo off
for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do (
echo %%G
set fullpath=%%G
set basename=%fullpath:~7%
echo %fullpath%
echo %basename%
)
这个脚本应该可以从任何地方运行,因此有有趣的 for 循环。它应该查看目录,然后执行一些操作。
在这个特定的目录中,还有另外 3 个目录bomslenovodb
:cpat
和finance
预期输出
e:\tmp\bomslenovodb
e:\tmp\bomslenovodb
bomslenovodb
e:\tmp\cpat
e:\tmp\cpat
cpat
e:\tmp\finance
e:\tmp\finance
finance
实际输出
First run
e:\tmp\bomslenovodb
ECHO is off.
ECHO is off.
e:\tmp\bomslenovodb
e:\tmp\cpat
ECHO is off.
ECHO is off.
e:\tmp\cpat
e:\tmp\finance
Second run
ECHO is off.
ECHO is off.
e:\tmp\finance
e:\tmp\bomslenovodb
e:\tmp\finance
ECHO is off.
e:\tmp\bomslenovodb
e:\tmp\cpat
e:\tmp\finance
Third run
ECHO is off.
e:\tmp\cpat
e:\tmp\finance
e:\tmp\finance
ECHO is off.
e:\tmp\finance
e:\tmp\bomslenovodb
e:\tmp\finance
e:\tmp\finance
Fourth run
e:\tmp\bomslenovodb
e:\tmp\cpat
e:\tmp\finance
e:\tmp\finance
e:\tmp\cpat
e:\tmp\finance
e:\tmp\finance
e:\tmp\finance
e:\tmp\finance
在我看来,它的set fullpath=%%G
行为并不像预期的那样,所以它的值设置不正确。
我在 Windows Server 2008 机器上,有什么想法吗?
答案1
典型的批次错误:-)
SET 命令运行正常。失败的是您的扩展。
%VAR%
扩展发生在语句被解析时,并且 FOR 循环内的所有命令都会被一次性解析。对于任何带括号的代码块也是如此。因此,和的值%fullpath%
在%basename%
整个 FOR 循环执行过程中都是恒定的 - 即在进入循环之前存在的值(在本例中未定义)。
解决方法是使用延迟扩展,它发生在命令执行之前。必须先启用延迟扩展才能setlocal enableDelayedExpansion
使用。扩展的语法更改为!VAR!
。
@echo off
setlocal enableDelayedExpansion
for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do (
echo %%G
set fullpath=%%G
set basename=!fullpath:~7!
echo !fullpath!
echo !basename!
)
但还有一个潜在的问题。文件名可以包含该!
字符,当启用延迟扩展时,任何包含该字符的 FOR 变量!
在扩展时都会被破坏。解决方案是在循环内打开和关闭延迟扩展。
@echo off
for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do (
echo %%G
set fullpath=%%G
setlocal enableDelayedExpansion
set basename=!fullpath:~7!
echo !fullpath!
echo !basename!
endlocal
)
如果您需要保护!
文字,并且需要变量赋值在迭代过程中保持不变,那么最简单的做法是使用 CALLed 过程,以便可以使用正常扩展。只需将 FOR 变量值传输到 CALL 参数即可。但使用 CALL 比将所有内容直接放入循环中要慢得多。
@echo off
for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do call :proc "%%G"
exit /b
:proc
echo %~1
set "fullpath=%~1"
set "basename=%fullpath:~7%"
echo %fullpath%
echo %basename%
exit /b