如何在 bash 安装脚本中处理相对路径?

4

我经常遇到这样的情况,希望提供一些“设置”或“安装”脚本,针对 git 存储库之类的内容,尽管这种情况也可以用于其他情况。

清楚地说一下:“设置脚本”指的是一个脚本,它会放置一些文件、检查一些东西、创建某些依赖关系等等。

问题在于,如果我想要使用相对于脚本的资源,或者想要创建指向存储库中文件的链接,我必须能够引用相对于存储库根目录的资源或构建绝对路径。

目前,我总是采用这种方法:

SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)
ROOT=$(realpath "$SCRIPT_DIR/..")

但这似乎很糟糕,因为它很难理解并且在每个repo甚至每个文件中都有重复。

有更好的方法吗?像这样的脚本是否不受欢迎?


这对于一个常见的脚本目录是可行的(我确实使用类似的东西),但在我的情况下,我正在谈论每个存储库一个脚本,应该可以放在任何地方。 - AK_is_curious
1
@Philippe 这个问题是如何编写一个脚本,引用与脚本在同一目录中的文件。这是一个常见的问题。假设脚本有一个关联的配置文件与其并列。它不能简单地打开 ./script.cfg -- 当前目录可能不是脚本和配置文件所在的位置,比如如果用户使用绝对路径 /path/to/script 而不是 cd /path/to; ./script 运行脚本。 - John Kugelman
FYI,我认为 realpath 在 Mac 上默认不包含,这意味着 ROOT 变量可能未被设置。 - Zebiano
3个回答

4

有更好的方法吗?

没有。

这样的脚本不受欢迎吗?

不是。这很正常。

还有其他方法吗?

我的手指已经习惯了键入 "$(dirname "$(readlink -f "$0")")",但那并不更好。

同时,请勿使用大写变量。它们不仅会喊叫,而且专门用于环境变量,例如 PWDLINESCOLUMNSDISPLAYUIDIFSUSER 等等。在您的脚本中,请使用小写变量。(我认为 ROOT 是一个非常常见且不好的变量名称。)


1
在git仓库中,您可以使用git rev-parse --show-toplevel查找工作树的根目录,然后从那里开始。
一般来说,这是一个相当困难的问题。有太多的方法可以调用能够改变$0实际含义的脚本,因此您不能真正依赖它。在我看来,在那里你所能做的最好的事情就是建立一个标准(例如,期望环境中出现某些值或坚持以./path/from/root/to/script执行脚本),如果不符合,则尝试以良好的错误消息退出。

很遗憾,git rev-parse --show-toplevel 只能在仓库内部使用,但我会记住的,谢谢。 - AK_is_curious
@AK_is_curious 好吧,那么,将其放入存储库必须成为您的标准的一部分。很抱歉,我不知道更好的方法。当然,您可以执行 git -C path/to/repo,但是没有比了解自己所在位置更好的替代方法。 - kojiro
1
我刚刚构建了这个命令:git -C "$(dirname "$0")" rev-parse --show-toplevel,它似乎运行得相当不错——至少在与 Git 存储库相关联时是如此。 - AK_is_curious

-1

这能提高脚本管理和可读性吗?

#!/usr/bin/env bash

source $HOME/common-tools/include.sh "${BASH_SOURCE[0]}"

echo $ROOT

在 $HOME/common-tools/include.sh 文件中:

SCRIPT_DIR=$(cd "$( dirname "$1" )" >/dev/null 2>&1 && pwd)
ROOT=$(realpath "$SCRIPT_DIR/..")


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接