setlocal 变量作用域
setlocal 与 endlocal 用来给批处理开一段变量沙箱:setlocal 之后的变量改动不会泄漏到外部环境,脚本结束或执行 exit /b 时该作用域会自动收尾。它是批处理防污染的标准做法,常与 enabledelayedexpansion 连用,用来解决 for 循环里变量展开时机不对的问题。
基本信息
| 适用平台 | Windows CMD 批处理 |
|---|---|
| 开启作用域 | setlocal [enabledelayedexpansion] |
| 结束作用域 | endlocal |
| 自动收尾 | 脚本结束或执行 exit /b 时 |
| 典型搭配 | enabledelayedexpansion 延迟展开 |
典型使用场景
- 子程序里临时使用变量,避免污染调用方的环境
- 循环中需要读取刚赋的新值,改用延迟展开变量
- 临时修改 PATH 或当前目录,退出后自动还原
- 多个脚本串联执行时保持各自环境互不影响
- 排查「变量改了却没生效」或「变量莫名被改」的问题
- 把批处理子程序写得更接近函数语义,降低维护成本
- 在公共脚本里做实验性改动时先隔离,避免影响调用方的后续逻辑
常用示例
常用示例
@echo off
setlocal enabledelayedexpansion
echo 旧值=%TMP_MODE%
set TMP_MODE=fast
echo 新值=%TMP_MODE%
REM 循环内取实时值要用感叹号:
for /l %%i in (1,1,3) do ( set N=%%i & echo 当前 !N! )
endlocal
REM 退出后 TMP_MODE 的改动不会保留到外部环境语句对照
| 语句 | 作用 | 注意 |
|---|---|---|
| setlocal | 开启局部作用域 | 可嵌套但需逐层收尾 |
| setlocal enabledelayedexpansion | 开启延迟展开 | 循环内取新值必备 |
| endlocal | 结束作用域并回滚 | 改动全部还原 |
| exit /b | 结束子程序并自动收尾 | 作用域随之结束 |
setlocal 内对 PATH、当前目录等变量的修改,在 endlocal 之后会被全部回滚,别在子程序里改完就指望它保留给调用方。需要把结果传出去时,用 exit /b 返回码或约定好的输出文件,而不是依赖变量直接可见。
嵌套 setlocal 时要逐层 endlocal,否则隔离边界会变得混乱;脚本正常结束或执行 exit /b 时系统会自动收尾,但显式配对可读性更好。同一文件里子程序较多时,统一在开头写一次 setlocal,比每段各写各的更不容易漏。