如何检测被source的Bash脚本是否接收到传入参数?
解决Bash脚本source时参数混淆问题
问题背景
现有source.sh脚本内容如下:
echo "$#" "$@"
执行时存在两种无法区分的场景:
- 继承shell参数场景:当前shell已通过
set设置位置参数,直接source脚本$ set -- argument $ . ./source.sh 1 argument - 传入source参数场景:source脚本时直接传入参数
$ . ./source.sh argument 1 argument
两种场景输出完全一致,无法判断参数是来自当前shell的位置参数,还是source脚本时主动传入的。
需求是让source.sh仅识别传给. source.sh的参数,同时支持直接执行(非source)的情况,期望实现以下输出:
$ set -- argument $ . ./source.sh 0 $ . ./source.sh argument 1 argument $ ./source.sh 0 $ ./source.sh argument 1 argument
解决方案
修改后的source.sh脚本如下:
#!/usr/bin/env bash if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then # 脚本被直接执行,直接使用当前的位置参数 echo "$#" "$@" else # 脚本被source,从Bash调用栈变量中提取source时传入的参数 local arg_count=${BASH_ARGC[0]} local -a source_args=() # BASH_ARGV存储参数为逆序,倒序提取得到正确顺序 for ((i=arg_count-1; i>=0; i--)); do source_args+=("${BASH_ARGV[i]}") done echo "$arg_count" "${source_args[@]}" fi
原理说明
${BASH_SOURCE[0]}:表示当前脚本的路径,${0}表示当前执行的进程名。当脚本被直接执行时,两者相等;当被source时,${0}是当前shell的进程名,与BASH_SOURCE[0]不等,以此区分执行方式。BASH_ARGC:数组类型,存储每个调用帧的参数数量。脚本被source时,BASH_ARGC[0]就是source操作传入的参数个数,不受当前shell位置参数影响。BASH_ARGV:数组类型,存储所有调用栈的参数,但以逆序排列。因此需要倒序提取BASH_ARGV中对应数量的元素,得到source时传入参数的正确顺序。
内容的提问来源于stack exchange,提问作者KamilCuk
相关产品推荐
相关产品推荐

