如何从脚本本身内获取Bash脚本所在的目录?

发布时间 2023-10-08 21:08:08作者: 小满独家

内容来自 DOC https://q.houxu6.top/?s=如何从脚本本身内获取Bash脚本所在的目录?

如何获取Bash脚本所在目录的路径,并在该脚本内部获取?

我想将一个Bash脚本用作另一个应用程序的启动器。我想将工作目录更改为Bash脚本所在的目录,以便我可以在该目录中的文件上进行操作,例如这样:

$ ./application


#!/usr/bin/env bash

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH\_SOURCE[0]}" )" &> /dev/null && pwd )

这是一个有用的一行命令,它将为您提供脚本的完整目录名称,无论从哪里调用它。

只要用于查找脚本的路径的最后一部分不是符号链接(目录链接是可以的),它就可以工作。如果您还想解析指向脚本本身的任何链接,您需要一个多行解决方案:

#!/usr/bin/env bash

SOURCE=${BASH\_SOURCE[0]}
while [ -L "$SOURCE" ]; do # 解析 $SOURCE,直到文件不再是符号链接
  DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
  SOURCE=$(readlink "$SOURCE")
  [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # 如果 $SOURCE 是相对符号链接,我们需要将其相对于符号链接文件所在的位置进行解析
done
DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )

这个最后的示例可以处理任何组合的别名、sourcebash -c、符号链接等。

注意:如果在运行此代码片段之前先使用cd命令更改了目录,则结果可能不正确!

此外,请当心 $CDPATH陷阱,以及用户智能地将cd重定向到输出的错误输出(包括转义序列,例如在Mac上调用update_terminal_cwd >&2)时可能出现的情况。在cd命令的末尾添加>/dev/null 2>&1可以解决这两种可能性。

要了解它的工作原理,请尝试运行这个更详细的版本:

#!/usr/bin/env bash

SOURCE=${BASH\_SOURCE[0]}
while [ -L "$SOURCE" ]; do # 解析 $SOURCE,直到文件不再是符号链接
  TARGET=$(readlink "$SOURCE")
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' 是一个指向 '$TARGET' 的绝对符号链接"
    SOURCE=$TARGET
  else
    DIR=$( dirname "$SOURCE" )
    echo "SOURCE '$SOURCE' 是一个指向 '$TARGET' 的相对符号链接(相对于 '$DIR')"
    SOURCE=$DIR/$TARGET # 如果 $SOURCE 是相对符号链接,我们需要将其相对于符号链接文件所在的路径进行解析
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR=$( dirname "$SOURCE" )
DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' 解析为 '$DIR'"
fi
echo "DIR is '$DIR'"

它会输出类似以下内容:

SOURCE './scriptdir.sh' 是一个指向 'sym2/scriptdir.sh' 的相对符号链接(相对于 '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' 解析为 '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'