如何在被父脚本source加载的子脚本中获取自身脚本名称
source执行场景下获取子脚本自身文件名的方案
问题本质
使用source(或.命令)加载脚本时,被加载脚本和父脚本共享同一个Shell进程,此时内置变量$0保存的是当前Shell进程的启动入口(也就是最外层执行的父脚本路径),所以给出的示例中两个脚本打印$0的结果全是./script1.sh,无法直接拿到被source的script2.sh的文件名。
可用实现
Bash环境(最常用场景)
Bash提供了内置数组变量BASH_SOURCE,数组索引0位存储的就是当前执行上下文对应的脚本路径,哪怕脚本是被source加载的,也能正确拿到自身路径。
直接修改script2.sh的代码即可:
#this is script 2 # 获取当前脚本的路径(兼容source执行场景) self_path="${BASH_SOURCE[0]}" # 如果只需要纯文件名,取路径基名即可 self_name="$(basename "$self_path")" echo "父脚本入口名\$0: $0" echo "当前脚本自身路径: $self_path" echo "当前脚本自身文件名: $self_name"
修改后再执行./script1.sh,script2.sh中就能正确输出自身的文件名script2.sh和对应路径。
多层source嵌套的场景同样适用:比如script1 source script2,script2再source script3,每个脚本内读取
${BASH_SOURCE[0]}都能拿到自身的路径,不会出现串值的问题。
跨Shell兼容写法
如果需要兼容Zsh等其他Shell,可以加版本判断做适配:
if [ -n "${BASH_VERSION:-}" ]; then self_path="${BASH_SOURCE[0]}" elif [ -n "${ZSH_VERSION:-}" ]; then self_path="${(%):-%N}" else # 纯POSIX Shell无原生内置变量支持该场景,仅能做有限兜底,兼容性较差 self_path="$0" fi self_name="$(basename "$self_path")"
注意事项
不要在source场景下依赖$0获取当前脚本名,这个变量的设计目的是存储进程启动入口,不会因为source操作发生变更,天生不适合这个使用场景。
内容的提问来源于stack exchange,提问作者A. Salas
相关产品推荐
相关产品推荐

