Bash:如何获取符号链接的真实路径?

41

/usr/local/bin文件夹中执行符号链接的文件时,是否有可能获取原始脚本的绝对路径?我知道原始文件的位置,并且我之所以知道是因为我正在链接它。但是,即使我移动了原始源代码(和符号链接),我也希望这个脚本能够正常工作。

#!/bin/bash
echo "my path is ..."

readlink是一种我可以在bash脚本中调用的函数吗?我正在尝试但不起作用=( - sensorario
readlink 是 coreutils 的一部分,它是一个二进制文件。 - Petr Skocik
11
readlink -f filename 命令可以让你获取链接目标文件的完整路径。 - Pavel Patrin
2
仅适用于GNU的readlink,不适用于BSD。 - kojiro
coreutils不是每个包含bash的系统都默认安装的。stat更加稳定可靠,但它在不同的操作系统中使用方法也有所不同。 - ghoti
许多工具可用于此。我从Debian上安装的一些工具包括realpathchasereadlink。毫无疑问,其他平台也有很多选择。 - Toby Speight
3个回答

40

readlink 不是标准命令,但在 Linux 和 BSD(包括 macOS)上很常见,并且这是回答你问题最直接的方法。BSD 和 GNU 的 readlink 实现不同,因此请阅读您所拥有的那个实现的文档。

如果 readlink 不可用,或者您需要编写一个不绑定特定实现的跨平台脚本:

如果符号链接也是一个目录,则

cd -P "$symlinkdir"

会将您带到解除引用的目录,因此

echo "I am in $(cd -P "$symlinkdir" && pwd)"

将会回显完全取消引用的目录。话说,cd -P 会取消引用整个路径,所以如果您在同一路径中有多个符号链接,可能会得到意外的结果。

如果符号链接指向的是文件而不是目录,则您可能不需要取消引用该链接。大多数命令会无害地跟随符号链接。如果您只想检查文件是否是链接,请使用 test -L


我的“#!/bin/bash”脚本执行命令:echo "I am in $(cd -P "$symlinkdir" && pwd)",输出“/usr/local/bin/ttmux: line 4: cd: : No such file or directory”。 - sensorario
7
pwd 命令也有 -P 选项。如果你已经在该目录中,可以使用 pwd -P 命令。如果你不在该目录中,则可以使用 (cd /path/w/symlinks/ && pwd -P) 命令。 - Boop
在执行 pwd -P 命令后,有没有一种方法可以执行 cd .. 命令(而不使用复制和粘贴)? - TaiwanGrapefruitTea
cd - 是什么意思,@TaiwanGrapefruitTea?此外,@Boop 的代码在括号中执行,并在子shell中执行,因此实际上并未更改当前shell的当前目录。 - Jasio

34

假设我们有一个真正的脚本或文件以及指向它的符号链接:

$ ls -la
-rwxr-xr-x 1 root    root  0 Mar 20 07:05 realscript.sh
lrwxrwxrwx 1 root    root 10 Mar 20 07:05 symlink -> realscript.sh

GNU coreutils 的一部分包含一些非常有用的命令:

$ realpath symlink
/home/test/realscript.sh

参见原始文档:

realpath realscript.sh
/home/test/realscript.sh

在脚本中,非常好的组合方式是使用dirname

$ dirname /home/test/realscript.sh
/home/test

总之,您可以在脚本中使用它。

echo  $( dirname $(realpath "symlink") )

要获取并存储真实脚本主目录的变量,并保存代码以获取真实路径脚本realscript.sh:

script_home=$( dirname $(realpath "$0") )
echo Original script home: $script_home

在Shell脚本中,“$0”被定义为“self”。

为了测试所有内容,我们将符号链接放入/home/test2/,更改一些其他内容,并从根目录运行/调用它:

$ /home/test2/symlink
/home/test
Original script home: /home/test
Original script is: /home/test/realscript.sh
Called script is: /home/test2/symlink

请尝试自行编写修正后的输出 :)

更新于2021年,还有一个命令:

readlink - 打印已解析的符号链接或规范文件名

描述 注意,realpath(1)是用于规范化功能的首选命令。


8
如果您正在使用GNU/Linux,您可以使用readlink命令:readlink -f $LINK 在macOS上,您也可以使用greadlink命令:greadlink -f $LINK

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