如何在Bash中结合变量使用大括号扩展通过mkdir创建年份子文件夹
两类Bash批量目录创建问题的根因与修复方案
核心底层逻辑
Bash 对命令行的解析有严格的优先级顺序,大括号扩展的执行时机远早于变量展开——只要大括号内部出现了 $ 开头的变量占位符,Bash 就会直接跳过括号内的范围语法(..)、分隔语法(,)的扩展逻辑,把整段括号内容当成普通字符串处理。你遇到的两类异常,本质都是踩了这个解析顺序的坑。
第一类异常:动态起止年份的范围扩展失效
问题原因
你写的 mkdir -p projects/{$START_DATE..$END_DATE} 执行时,Bash 先做大括号扩展,此时 $START_DATE、$END_DATE 还没被替换成具体的年份数字,识别到括号内有变量就直接放弃了范围展开,最终把整段 {2018..2021} 当成了单级路径名创建目录。
正确修复方式
- 方式1:通过
eval触发二次解析,等变量完成值替换后,再执行大括号扩展。写法为:
注意必须把完整命令用双引号包裹,避免解析顺序错位。eval "mkdir -p projects/{$START_DATE..$END_DATE}" - 方式2:用算术循环遍历生成路径,兼容性更强,不依赖特殊解析逻辑,也是生产脚本里更推荐的写法:
这种写法哪怕在不支持动态大括号范围的旧版本Bash上也能正常运行。for (( year = START_DATE; year <= END_DATE; year++ )); do mkdir -p "projects/$year" done
第二类异常:存入变量的路径列表不做分隔展开
问题原因
你尝试写 SUB_PROJECTS={$START_DATE,$END_DATE} 赋值、再执行 mkdir -p projects/$SUB_PROJECTS 时,同样踩了解析顺序的坑:
- 变量赋值阶段本来会触发大括号扩展,但因为括号内有变量,Bash 直接把整段
{2018,2021}当字符串存进了变量,没有展开成两个独立的年份值 - 执行
mkdir时,Bash 已经走完了大括号扩展的流程,展开$SUB_PROJECTS拿到存储的字符串后,不会再识别括号里的逗号分隔符,最终把整段字符串当成单一路径名。
正确修复方式
- 如果需要把路径列表独立存储、方便后续调整,用数组存储展开后的独立值,不要把带大括号的原始字符串直接存变量:
# 初始化存储子目录名的数组 sub_projects=() for (( year = START_DATE; year <= END_DATE; year++ )); do sub_projects+=("$year") done # 批量创建目录 mkdir -p "projects/${sub_projects[@]}" - 如果一定要在赋值阶段用大括号扩展生成列表,同样可以通过
eval触发正确的解析顺序:eval "sub_projects=({$START_DATE..$END_DATE})" mkdir -p "projects/${sub_projects[@]}"
注意:
eval仅适合处理脚本内硬编码的可信参数,不要对用户可控的输入内容使用该语法,避免出现任意命令执行的安全风险。
内容的提问来源于stack exchange,提问作者bmalbusca
相关产品推荐
相关产品推荐

