如果我运行批处理文件
setlocal
chdir ..
目录未更改,但如果我运行
setlocal
endlocal
chdir ..
它正常工作。这必须与setlocal完全一致。但是,当您阅读setlocal的定义时,并不完全明显,这与环境变量的显示方式有关。我希望这是一个很好的机会来解释setlocal实际上做了什么以及为什么它干扰了chdir。
答案 0 :(得分:2)
SETLOCAL(help setlocal
或setlocal /?
)的帮助文档实际上很好地解释了这种情况。唯一不明显的是“ 环境变化的本地化 ”不仅包括环境变量,还包括当前目录,ECHO状态和延迟扩展和扩展状态。可能会有更多,但我现在想不到它。
实际上解释了绊倒你的事情:“ 当到达批处理脚本的末尾时,对该批处理脚本发出的任何未完成的SETLOCAL命令执行隐含的ENDLOCAL。 / em> “未说明对被调用的子程序也是如此。
当您的批处理脚本结束时,隐含的ENDLOCAL会“擦除”CHDIR的效果。您的第二个代码中的显式ENDLOCAL会使您返回到根环境,因此您的CHDIR将被保留。
更新
当前目录不是环境变量,即使您通常可以使用%CD%
获取当前值。你可以通过SET CD
证明它 - 它可能会给你“环境变量CD未定义”。如果使用set "CD=some value"
显式定义自己的真实CD变量,则%CD%
将返回您指定的值,而不是当前目录。
原始的SETLOCAL命令无法在旧的COMMAND.COM天中控制延迟扩展或扩展。引入CMD.EXE时添加了启用/禁用DelayedExpansion和启用/禁用扩展选项。这就是MS决定如何实现该功能。它不一定是这样的。在许多方面,如果没有SETLOCAL / ENDLOCAL,您将无法控制这些状态,这很不幸。我经常希望能在不本地化环境的情况下启用或禁用延迟扩展。
答案 1 :(得分:0)
我遇到了这种行为,编写批处理文件以根据命令行参数和一堆内部逻辑更改目录。
使用setlocal和更改目录的一种方法是递归调用批处理文件,将目标路径作为字符串返回,并让顶级调用者 cd 。
在此示例中,批处理文件在命令行上使用 p 或 px 来更改为特定目录:
@echo off
if not "%1"=="recurse" (
for /f "delims=" %%i in ('%0 recurse %1') do cd %%i
exit /b
)
setlocal
rem Do things here with "local" variables
if "%2"=="p" (
echo "c:\program files"
) else if "%2"=="px" (
echo "c:\program files (x86)"
)
注意: