为什么setlocal会干扰windows批处理文件中的chdir?

5 batch-file delayedvariableexpansion chdir

如果我运行批处理文件

setlocal
chdir ..
Run Code Online (Sandbox Code Playgroud)

目录未更改,但如果我运行

setlocal
endlocal 
chdir ..
Run Code Online (Sandbox Code Playgroud)

它正常工作.这必须与setlocal完全一致.但是,当您阅读setlocal的定义时,并不完全明显,这与环境变量的显示方式有关.我希望这是一个很好的机会来解释setlocal实际上做了什么以及为什么它干扰了chdir.

dbe*_*ham 5

SETLOCAL (help setlocal或setlocal /?)的帮助文档实际上很好地解释了这种情况。唯一不明显的是,“环境变化的本地化”不仅包括环境变量,还包括当前目录,以及延迟扩展和扩展状态。可能还有更多,但我现在想不出来。

使您失望的事情实际上已经很好地解释了:“当到达批处理脚本的末尾时,将为该批处理脚本发出的任何未完成的 SETLOCAL 命令执行一个隐含的 ENDLOCAL。 ” 未说明的是,同样适用于称为子程序。

当您的批处理脚本结束时,隐含的 ENDLOCAL 会“擦除”您的 CHDIR 的效果。您在第二个代码中的显式 ENDLOCAL 使您返回到根环境,因此您的 CHDIR 将被保留。


更新

当前目录不是环境变量,即使您通常可以使用%CD%. 您可以通过 tring 来证明它SET CD- 它可能会给您“未定义环境变量 CD”。如果您使用 明确定义自己的真实 CD 变量set "CD=some value",%CD%则将返回您分配的值,而不是当前目录。

在旧的 COMMAND.COM 时代,原始的 SETLOCAL 命令并没有控制延迟的扩展或扩展。启用/禁用 DelayedExpansion 和启用/禁用扩展选项是在引入 CMD.EXE 时添加的。这正是 MS 决定实施该功能的方式。不必如此。在许多方面,不幸的是,如果没有 SETLOCAL/ENDLOCAL,您就无法控制这些状态。我经常希望可以在不本地化环境的情况下启用或禁用延迟扩展。