批处理脚本首次运行无法获取目录名,二次运行才正常
问题原因分析
你遇到的这个问题其实是批处理脚本里非常常见的变量延迟扩展坑。当批处理执行一个包含多行代码的代码块(比如你的IF "%1"==""分支里的多行命令)时,它会先对整个代码块里的所有%变量%进行一次性展开,而不是执行到对应行时才读取变量的最新值。
第一次运行脚本时,set DIR=%%~n*这行还没执行,%DIR%还是空值,所以set DJANGO_SETTINGS_MODULE=%DIR%.dev_settings会被展开成set DJANGO_SETTINGS_MODULE=.dev_settings;而第二次运行时,DIR变量已经在上一次运行后被保留在终端环境里了,所以能正确展开。
解决办法
要解决这个问题,需要开启批处理的延迟扩展功能,这样就能在代码块执行过程中实时读取变量的最新值。具体步骤如下:
- 在脚本开头添加
setlocal enabledelayedexpansion来启用延迟扩展 - 将代码块里的
%DIR%替换成!DIR!(延迟扩展的变量语法是用感叹号包裹)
修改后的完整脚本
@echo off setlocal enabledelayedexpansion IF "%1"=="-r" ( set "DJANGO_SETTINGS_MODULE=" ) ELSE IF "%1"=="" ( start cmd /c prp-sql for %%* in (.) do set DIR=%%~n* set DJANGO_SETTINGS_MODULE=!DIR!.dev_settings ) ELSE IF "%2"=="" ( start cmd /c prp-sql set DJANGO_SETTINGS_MODULE=%1.dev_settings ) ELSE ( start cmd /c prp-sql set DJANGO_SETTINGS_MODULE=%1.%2 ) endlocal
额外说明
setlocal和endlocal会把脚本内的变量变化限制在脚本运行期间,避免污染终端的全局环境(如果不需要这个限制,可以去掉endlocal,但建议保留)- 只有在多行代码块(比如IF/ELSE、FOR循环内部)里才需要用延迟扩展,像后面的
%1.dev_settings这种直接使用命令行参数的场景不需要修改
内容的提问来源于stack exchange,提问作者Sam Tuson
相关产品推荐
相关产品推荐

