我的一些同事喜欢在他们的 BASH 脚本顶部写以下内容来确定包含该脚本的目录:
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
而我则倾向于以下做法:
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
(请注意,在大多数情况下,我们并不关心解析符号链接,因此我们倾向于使用这些而不是例如readlink
)
cd ... && pwd
与 -only 方法相比,该方法有什么优点dirname
吗?它似乎只是执行了额外的步骤来实现完全相同的结果,但我想确保我没有遗漏任何细微差别。
要点:
更确切地说应该是:
它为您提供了一个绝对路径(以及
-P
,规范的绝对路径,realpath()
),而$BASH_SOURCE
(在 bash 中$var
是 的缩写,${var[0]}
就像在 ksh 中一样)很可能是一个相对路径,例如../file.bash
。如果没有
-P
,在 的情况下../file.bash
,cd ..
很可能会将您带到与脚本默认所在的目录不同的目录(再次像在 ksh 中引入了(mis)功能)cd
进行逻辑遍历,其中cd ..
没有chdir("..")
而是chdir(dirname($PWD))
(并且$PWD
将具有符号链接组件,如果您cd
之前已经进入带有符号链接组件的路径)。我们将其设置
CDPATH
为空字符串(就其cd
而言,这相当于取消设置),以防它被设置为其他内容,例如,环境中有一个同名变量,否则cd
带有相对路径(如本例所示BASH_SOURCE=dir/file.bash
)的变量可能会将您带到其他地方。CDPATH
全局取消设置可能是一个好主意,但如果该脚本旨在被引用,则可能不可接受。请注意,如果 的目录名
BASH_SOURCE
或其实际路径以换行符结尾(因为命令替换会删除所有dirname
尾随的换行符,而不仅仅是/pwd
为输出添加的换行符),或者例如 (因为是$BASH_SOURCE
的缩写),它仍然无法正常工作。-/file
cd -
cd -- "$OLDPWD"
解决后者的问题,更普遍地讲,更接近
cd
非chdir()
shell 编程语言中发现的问题,可以使用POSIX 建议的辅助函数来实现:相对路径前缀为
./
可避免需要--
,并解决与不解释为上一个目录相反的-
问题。请参阅此处了解为什么对空字符串进行特殊处理。该前缀还会禁用处理,因此除了提醒该帮助程序禁用处理之外,不需要上述内容。./-
-
./
CDPATH
CDPATH=
chdir
CDPATH
在 zsh 中,你只需执行以下操作:
或者:
其中
:P
为您提供realpath()
和:h
头部(目录名,类似于 csh)。$0
如果恰好是符号链接本身,则两者都不一定会给出相同的结果。这些不存在上述 bash 方法的任何问题。
坦率地说,我认为这两者都是不必要的复杂(我错了;请参阅Stéphane 的回答,其中解释了如果您需要解析绝对路径,这就是这样做的方法)。即使是更简单的版本仍然会调用不需要的外部命令。为什么不直接这样做:
至于这两个命令,我认为使用两个外部命令这种更加复杂的方法没有任何好处。
pwd
如果可以使用,为什么要运行$PWD
,但为什么要运行这么多命令呢?如果您需要解析符号链接,那么我可以理解引入外部命令,但对于像这样简单的事情呢?现在,有些极端情况会导致此方法失效。正如 Stéphane Chazelas 在一条(现已删除)评论中解释的那样:
这是否与您的情况相关只有您自己知道。
另外,你真的不想使用大写字母作为 shell 变量名。因为按照惯例,全局环境变量是大写的,所以将大写字母用于你自己的局部变量是一种不好的做法,因为这会导致命名冲突和难以发现错误。