如何解析shell脚本中的符号链接

给定绝对路径或相对路径(在类Unix系统中),我想在解析任何中间符号链接后确定目标的完整路径。 奖励积分也可以同时解析〜用户名表示法。

如果目标是一个目录,可以将chdir()放到目录中,然后调用getcwd(),但我真的想从shell脚本执行此操作,而不是编写C助手。 不幸的是,shell有一种倾向,试图隐藏用户的符号链接的存在(这是OS X上的混淆):

$ ls -ld foo bar
drwxr-xr-x   2 greg  greg  68 Aug 11 22:36 bar
lrwxr-xr-x   1 greg  greg   3 Aug 11 22:36 foo -> bar
$ cd foo
$ pwd
/Users/greg/tmp/foo
$

我想要的是一个函数resolve(),当从上面示例中的tmp目录执行时,resolve(“foo”)==“/ Users / greg / tmp / bar”。


根据标准, pwd -P应该返回解析了符号链接的路径。

来自unistd.h C函数char *getcwd(char *buf, size_t size)应该具有相同的行为。

getcwd pwd


readlink -f "$path"

编者按:上面的代码与GNU readlink和FreeBSD / PC-BSD / OpenBSD readlink ,但不在10.11版本的OS X上。
GNU readlink提供了额外的相关选项,如-m用于解析符号链接,无论最终目标是否存在。

请注意,自GNU coreutils 8.15(2012-01-06)以来,有一个可用的实际路径程序比以上更不灵活和更灵活。 它也与同名的FreeBSD util兼容。 它还包括在两个文件之间生成相对路径的功能。

realpath $path

[下面的管理添加评论来自halloleo -danorton]

对于Mac OS X(至少通过10.11.x),请使用不带-f选项的readlink

readlink $path

编者按:这不会解决符号链接递归,因此不会报告最终目标; 例如,给定符号链接a指向b ,后者又指向c ,这将只报告b (并且不会确保它被输出为绝对路径)。
在OS X上使用以下perl命令来填补缺失readlink -f功能的空白:
perl -MCwd -le 'print Cwd::abs_path(shift)' "$path"


“pwd -P”似乎可以工作,如果你只是想要目录,但如果由于某种原因,你想要的实际可执行文件的名称,我认为这不会有帮助。 这是我的解决方案:

#!/bin/bash

# get the absolute path of the executable
SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0")

# resolve symlinks
while [[ -h $SELF_PATH ]]; do
    # 1) cd to directory of the symlink
    # 2) cd to the directory of where the symlink points
    # 3) get the pwd
    # 4) append the basename
    DIR=$(dirname -- "$SELF_PATH")
    SYM=$(readlink "$SELF_PATH")
    SELF_PATH=$(cd "$DIR" && cd "$(dirname -- "$SYM")" && pwd)/$(basename -- "$SYM")
done
链接地址: http://www.djcxy.com/p/9735.html

上一篇: How to resolve symbolic links in a shell script

下一篇: Echo newline in Bash prints literal \n