除非使用的外壳提供了POSIX规范的扩展,否则源脚本的位置不可用。您可以使用以下代码段进行测试:
env -i PATH=/usr/bin:/bin sh -c '. ./included.sh' | grep included
哪里included.sh
包含
echo "$0"
set
在bash中,源脚本的名称在中$BASH_SOURCE
。在zsh中(在zsh兼容模式下,而不是在sh或ksh兼容模式下),它在其中$0
(请注意,在函数中,$0
是函数名)。在pdksh和破折号中,它不可用。在ksh93中,此方法未提供解决方案,但是包含的脚本的完整路径为${.sh.file}
。
如果需要bash或ksh93或zsh足够好,则可以使用以下代码段:
if [ -n "$BASH_SOURCE" ]; then
this_script=$BASH_SOURCE
elif [ -n "$ZSH_VERSION" ]; then
setopt function_argzero
this_script=$0
elif eval '[[ -n ${.sh.file} ]]' 2>/dev/null; then
eval 'this_script=${.sh.file}'
else
echo 1>&2 "Unsupported shell. Please use bash, ksh93 or zsh."
exit 2
fi
您可以通过查看外壳程序打开了哪些文件来尝试猜测脚本的位置。实验上,这似乎适用于dash和pdksh,但不适用于bash或ksh93,bash或ksh93至少对于短脚本而言,在他们开始执行脚本时就关闭了该脚本文件。
open_file=$(lsof -F n -p $$ | sed -n '$s/^n//p')
if [ -n "$open_file" ]; then
# best guess: $open_file is this script
fi
如果该脚本源自具有重定向功能的复杂脚本中,则该脚本可能不是具有最大编号的描述符的文件。您可能要遍历打开的文件。无论如何,这不能保证能正常工作。定位源脚本的唯一可靠方法是使用bash,ksh93或zsh。
如果可以更改界面,则不必采购脚本,而是让脚本打印出要传递给eval
调用方的shell片段。这就是设置环境变量的脚本通常要做的事情。它使您的脚本可以独立于调用者的shell和shell配置的变化而编写。
#!/bin/sh
FOO_DIR=$(dirname -- "$0")
cat <<EOF
FOO_DIR='$(printf %s "$FOO_DIR" | sed "s/'/'\\''/g")'
PATH="\$PATH:$FOO_DIR/bin";
export FOO_DIR PATH
EOF
在呼叫者中: eval "`/path/to/setenv`"