我试图做一个简单的批处理(这不是整个事情,但这是使一切都失败的部分)
@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% )
这个剧本应该是从任何地方运行的,因此这个剧本有趣的循环。 它应该查看目录,然后做一些东西。
在这个特定的目录中,还有另外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的机器,任何想法?
经典批次错误:-)
SET命令工作正常。 这是你的扩张失败。
parsing语句时发生%VAR%扩展,并且FOR循环中的所有命令都一次被parsing。 任何括号的代码块也是如此。 因此,在执行FOR循环的过程中, %fullpath%和%basename%是不变的 – input循环之前存在的值(在这种情况下是未定义的)。
解决方法是使用延迟扩展,即在命令执行之前发生。 在使用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! )
但是还有一个潜在的问题。 文件名可以包含! 字符和任何FORvariables包含! 当延迟扩展被启用时,将在扩展时被破坏。 解决scheme是在循环内切换延迟扩展和closures。
@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 )
如果你需要保护! 文字,你需要你的variables分配来持续迭代,那么最简单的事情就是使用一个CALLed过程,这样你就可以使用正常的扩展。 只需将FORvariables值转换为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