Bash中如何仅在选项已设置时将其传递给下游调用脚本
实现方案
核心逻辑
使用独立数组存储仅用户显式传入的、需要透传给子脚本的参数,未被传入的参数不会加入数组,自然沿用do-foo-for-thing.sh内部维护的默认值,无需在多任务脚本中重复维护默认规则。
前置修正:现有脚本的通用bug
两个原脚本存在以下基础问题,必须先修正才能正常工作:
- getopts参数配置为小写
a:b:c:p:,但case分支写的是大写B)、C)、P),这类分支永远不会被触发,参数完全解析失败。 - 原
do-foo-for-many-things.sh中调用子脚本的路径写为./do-for-for-thing.sh,属于笔误,需修正为正确的./do-foo-for-thing.sh。 - 原
for P inls D``的写法会因为文件名带空格、特殊字符出现解析错误,需替换为更安全的glob匹配方式。
修正后的do-foo-for-thing.sh参数解析部分应为:
A=default-A B=default-B C=default-C P="" if [ $# -ge 1 ]; then OPTIND=1 while getopts "a:b:c:p:" opt; do case "$opt" in a) A=$OPTARG ;; b) B=$OPTARG ;; # 修正原大写B的错误 c) C=$OPTARG ;; # 修正原大写C的错误 p) P=$OPTARG ;; # 修正原大写P的错误 \?) echo "Unrecognized option: -$OPTARG" >&2; exit 1 ;; esac done shift $((OPTIND-1)) fi do-foo-that-uses-values-A-B-and-C-on-P
改造do-foo-for-many-things.sh
核心改动点:
- 新增空数组
child_args存储需要透传的参数 - getopts解析到
a/b/c选项时,仅把显式传入的参数追加到数组中 - 替换易出错的
ls命令,用glob匹配兼容带特殊字符的文件名 - 调用子脚本时直接展开数组,无需额外判断参数是否存在
改造后的完整代码:
#!/bin/bash # 存储需要透传给子脚本的显式传入参数 child_args=() OPTIND=1 while getopts "d:a:b:c:" opt; do case "$opt" in d) D=$OPTARG ;; a) # 收到用户显式传入的-a,追加到透传数组 child_args+=("-a" "$OPTARG") ;; b) child_args+=("-b" "$OPTARG") ;; c) child_args+=("-c" "$OPTARG") ;; \?) echo "Unrecognized option: -$OPTARG" >&2; exit 1 ;; esac done shift $((OPTIND-1)) # 遍历D目录下的所有条目,兼容带空格的文件名 for P in "$D"/*; do # 跳过目录不存在的异常场景 [ -e "$P" ] || continue # 调用子脚本:传入所有显式收集的透传参数 + 固定传的-p参数 ./do-foo-for-thing.sh "${child_args[@]}" -p "$P" done
运行效果
- 如果用户调用多任务脚本时只传
-d ./target_dir -a custom-A,实际传给子脚本的命令为./do-foo-for-thing.sh -a custom-A -p 某条目,子脚本自动使用内置的default-B、default-C作为默认值。 - 所有参数默认值仅在
do-foo-for-thing.sh中维护,后续修改默认值只需改动子脚本一处即可,无需同步修改多任务脚本。
内容的提问来源于stack exchange,提问作者meta
相关产品推荐
相关产品推荐

