您可以使用${BASH_SOURCE[1]}
获取调用该函数的脚本,但这并不总是采用绝对路径形式。您可以通过 , 或其他基于 shell 脚本的解决方案获得它的绝对路径readlink -m
,realpath
但是如果您的脚本不时更改目录,则将相对路径转换为绝对路径将不再准确,因为这些工具基于当前目录得到实际的形式。
但是有一种解决方法,但这要求您在调用(采购)包含该函数的脚本之前不要更改脚本中的目录。您必须将当前目录保存在该脚本本身中,然后通过该目录形成绝对路径。包含脚本后,您可以自由更改目录。举个例子:
ORIGINAL_PWD=$PWD
function x {
local CALLING_SCRIPT="${BASH_SOURCE[1]}"
if [[ -n $CALLING_SCRIPT ]]; then
if [[ $CALLING_SCRIPT == /* ]]; then
CALLING_SCRIPT=$(readlink -m "$CALLING_SCRIPT")
else
CALLING_SCRIPT=$(readlink -m "$ORIGINAL_PWD/$CALLING_SCRIPT")
fi
echo "Calling script: $CALLING_SCRIPT"
else
echo "Caller is not a script."
fi
}
或者
ORIGINAL_PWD=$PWD
function getabspath {
local -a T1 T2
local -i I=0
local IFS=/ A
case "$1" in
/*)
read -r -a T1 <<< "$1"
;;
*)
read -r -a T1 <<< "/$PWD/$1"
;;
esac
T2=()
for A in "${T1[@]}"; do
case "$A" in
..)
[[ I -ne 0 ]] && unset T2\[--I\]
continue
;;
.|'')
continue
;;
esac
T2[I++]=$A
done
case "$1" in
*/)
[[ I -ne 0 ]] && __="/${T2[*]}/" || __=/
;;
*)
[[ I -ne 0 ]] && __="/${T2[*]}" || __=/.
;;
esac
}
function x {
local CALLING_SCRIPT="${BASH_SOURCE[1]}"
if [[ -n $CALLING_SCRIPT ]]; then
if [[ $CALLING_SCRIPT == /* ]]; then
getabspath "$CALLING_SCRIPT"
else
getabspath "$ORIGINAL_PWD/$CALLING_SCRIPT"
fi
echo "Calling script: $__"
else
echo "Caller is not a script."
fi
}
您还可以使用 FUNCNAME 和 BASH_LINENO 来更具体地处理错误。我只是不确定 Bash 3.2 是否已经支持它们。
如果您实际上拥有 Bash 4.0+,则可以使用关联数组来映射绝对路径,但如果有两个具有相同名称或以几乎相似名称调用的脚本,则可能会覆盖一个值。由于我们无法从 BASH_SOURCE 中选择密钥,因此无法解决此问题。
补充说明:您还可以防止您的脚本被不必要地多次获取,因为它只需要通过Shell Script Loader之类的解决方案进行一次。您也可以通过它找到便利。