从 Bash 脚本中获取完整路径

从 Bash 脚本中获取完整路径

我有一个使用相对路径的 bash 脚本。它需要有一个与存储脚本的目录相同的工作目录。只要我从提示符启动它,它就可以正常工作,因为我可以先 cd 到脚本的目录。但是,当我在 /etc/cron.hourly 中创建指向脚本的符号链接时,脚本会中断。

我需要一种方法使 bash 脚本将目录更改为存储脚本的目录。但是,到目前为止我还没有成功。即使脚本是通过符号链接从 cron 调用的,是否有一种简单的方法可以做到这一点?

答案1

正常情况下,shell 总是知道脚本的路径,因为它必须读取它。请注意,在某些情况下情况并非如此,例如setuid 脚本在支持它们的操作系统上(不是 Linux)——但 setuid shell 脚本无论如何都是一个坏主意。最重要的是,脚本可能在 shell 打开它的时间和您尝试使用它执行任何操作的时间之间发生了移动。因此,仅在不存在安全性或可靠性问题时才使用脚本的路径。具有已知结构的软件包是一个有效的用例。

传递给 shell 解释器的脚本路径可在特殊参数中找到$0。这可能是相对路径,因此如果您要使用它,请在更改到另一个目录之前执行此操作。如果您知道脚本在此期间不会被移动,则可以使用它。

由于$0可能是符号链接,因此您需要获取其目标。没有 POSIX 方法可以做到这一点,但在 Linux(GNU coreutils 或 BusyBox)和最近的 BSD 上您可以使用readlink -f使用规范绝对路径

script_path_in_package=$(readlink -f -- "$0")
script_directory=${script_path_in_package%/*}

请注意,这限制了您构建包的方式。例如,您不能将脚本放在独立于体系结构的目录树中,并在每个特定于体系结构的目录树内链接到它。

答案2

我不记得从哪里得到这个,所以我可以正确地归因,但我已经使用它很长时间来获取我正在执行的脚本的“规范”路径。我所说的规范,是指不带“.”的绝对路径。或其中的“..”。

CANON=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)/$(basename -- "$0")")

如果需要,我将使用 $CANON 上的基本名称和目录名称来获取这些值。

答案3

你应该能够做到这一点。

  • $0 参数扩展为调用脚本时的完整路径(包括名称)。
  • 内置shell函数测试(或者[ ])可以使用以下命令测试路径是否是符号链接-L
  • ls -l,如果应用于符号链接,将给出单行输出,并将真实路径作为最终字段。

这足以让您发现源头的位置。当然,这可能是一个符号链接,这需要您递归地执行此操作......

答案4

该变量$0保存程序的名称。做

cd $(dirname $( readlink $0) )

更改到程序所在的目录。

是的,$0 可能有问题,如果用于一般情况。我认为在明确定义设置的特定情况下将其用于自己的工作是可以的。

特别是,脚本无论如何都不应该使用其目录进行工作,应该依赖环境变量或配置文件,所以为什么要关心“自从您启动脚本以来,有人可能已经移动了脚本”或如何 ksh 这样的细节将解释它(假设我们知道这是一个 bash 脚本)。

相关内容