下面两个命令的区别是什么? {#下面两个命令的区别是什么?}
-
@setlocal EnableExtensions
-
@setlocal EnableExtensions EnableDelayedExpansion
两个命令都使用了 setlocal
,它用于局部化环境变量的更改,这样在当前批处理脚本或命令块中所做的更改不会影响外部的环境。但是,这两个命令有以下主要区别:
- @setlocal EnableExtensions
这个命令仅启用命令扩展。命令扩展增加了Windows命令提示符中许多原始命令的功能,例如for
和if
。这些扩展在现代的Windows版本中默认是启用的,但这个命令确保在脚本中它们始终是启用的,无论外部环境如何。 - @setlocal EnableExtensions EnableDelayedExpansion
这个命令启用命令扩展并启用延迟的环境变量扩展。延迟的环境变量扩展允许在批处理脚本的循环或代码块内部更改和立即读取变量的值。在启用延迟扩展的脚本中,你可以使用!variable!
代替%variable%
来获取变量的实时值。
总结 {#总结}
- 第一个命令仅启用命令扩展。
- 第二个命令启用命令扩展并启用延迟的环境变量扩展。
在编写批处理脚本时,根据你的具体需求选择合适的选项。如果你需要在循环中动态修改和读取变量的值,那么你应该启用延迟扩展。
简而言之,@setlocal EnableExtensions EnableDelayedExpansion
包含了 @setlocal EnableExtensions
的所有功能,并额外增加了延迟扩展的能力。因此,@setlocal EnableExtensions
可以被视为 @setlocal EnableExtensions EnableDelayedExpansion
的一个子集。
为什么 EnableDelayedExpansion 的前面要有 EnableExtensions,我看到的都有这个 {#为什么-EnableDelayedExpansion-的前面要有-EnableExtensions,我看到的都有这个}
很好的问题!事实上,虽然在很多情况下你会看到 EnableExtensions
和 EnableDelayedExpansion
一起使用,但技术上 EnableDelayedExpansion
并不需要 EnableExtensions
作为前置条件。两者都是 setlocal
命令的独立选项。
然而,这两个选项经常一起使用是因为以下原因:
- 向后兼容性 :在早期的 Windows 版本中,命令扩展默认是禁用的。为了确保脚本在所有环境中都能正常工作,脚本作者会明确启用命令扩展。因此,习惯上,人们在使用其他命令扩展功能(如
EnableDelayedExpansion
)时,也会启用EnableExtensions。
- 清晰和明确 :明确地包含
EnableExtensions
可以使脚本的意图更加明确。其他读取或维护脚本的人可以清楚地看到命令扩展已被启用。 - 习惯:由于很多示例和教程都同时使用这两个选项,所以许多脚本作者也采用了这种方式,即使技术上它们不是紧密关联的。
总之,尽管 EnableDelayedExpansion
不需要 EnableExtensions
作为前置条件,但出于上述原因,你经常会看到它们一起使用。
为什么EnableExtensions的前面要有 @setlocal ?为什么只有 EnableExtensions的bat脚本会报错? {#为什么EnableExtensions的前面要有-setlocal-?为什么只有-EnableExtensions的bat脚本会报错?}
@setlocal
和 EnableExtensions
通常一起使用来达到特定的目的,但它们的功能和目的是不同的。让我们先详细了解这两个命令,然后再讨论为什么通常会看到它们一起使用。
- setlocal :此命令用于将环境变量的更改限制在当前脚本或命令块中。这意味着,任何在使用
setlocal
之后对环境变量的更改都不会影响到脚本外部的环境。它为脚本提供了一个"沙盒"环境,确保脚本中的操作不会意外地更改全局环境。 - EnableExtensions:此选项启用命令扩展,这些扩展增强了 CMD 中的某些命令的功能。在现代版本的 Windows 中,这些命令扩展默认是启用的,但通过明确地使用此选项,你可以确保脚本在所有环境中都表现一致。
现在,为什么要使用 @setlocal EnableExtensions
而不仅仅是 EnableExtensions?
- 单独使用
EnableExtensions
会导致错误,因为EnableExtensions
不是一个独立的命令,而是setlocal
命令的一个选项。你不能单独使用它,因为 CMD 不知道你想要做什么。它需要setlocal
命令来理解你的意图。 @
符号用于阻止命令本身在执行时被打印到控制台。这样,当你运行脚本时,它不会显示setlocal EnableExtensions
这行命令,使输出看起来更加整洁。
因此,当你在批处理脚本中使用 @setlocal EnableExtensions
时,你实际上是在告诉 CMD:"我要开始一个新的局部环境,并在这个环境中启用命令扩展"。这确保了你脚本中的命令将以你预期的方式运行,并且对环境变量所做的任何更改都不会影响到脚本之外的环境。
参考链接:https://zhuanlan.zhihu.com/p/645242913