在 zsh/Bash 中进行通配时部分解析/遵循符号链接

在 zsh/Bash 中进行通配时部分解析/遵循符号链接

假设我有一个文件a是到 的符号链接b,而该文件又是到 的符号链接c

使用 zsh 的:A修饰符,通配 a 将产生绝对路径,解析所有符号链接,因此将扩展到(在具有该库的系统上)a(:A)的绝对路径。crealpath

是否有可能获得b(绝对或相对,但直接作为通配符的结果,而不是例如通过查看 的输出ls -l)甚至文件达到任意符号链接深度?

Bash 的解决方案也值得了解。

答案1

您始终可以创建一个与 glob 限定符一起使用的函数+

$ zmodload zsh/stat
$resolve() { [[ -L $REPLY ]] && stat -A REPLY +link -- ${1-$REPLY}; }
$ print -r - a(+解析)
$ print -r - a(+解析:a)
/home/stephane/b (尽管请参阅下面的警告)

请注意,如果这样做a(+resolve+resolve),第二个resolve仍将在原始文件名 ( ) 上调用,而不是在第一个( )a的结果上调用。但是你可以这样做:resolveb

$ print -r - a(e['resolve && resolve'])
c

将两个resolves 链接起来。然而(并且警告也适用于:a上面的用法),尽管它适用于这个特定的示例,但在一般情况下这不是一个有效的事情,因为当相对路径时,符号链接的目标是相对于符号链接,而不是当前工作目录,所以如果dir/link指向foo,那就是文件dir/foo,而不是foo,所以它仅在解析当前工作目录中的符号链接时有效。

resolve不过,如果我们改变它,那么它就会计算符号链接目标的完整路径,这将不再是一个问题:

resolve() {
  local target
  [[ -L $REPLY ]] &&
    stat -A target +link -- ${1-$REPLY} &&
    case $target in
      (/*) REPLY=$target;;
      (*) REPLY=${REPLY:h:a}/$target;;
    esac
}

bash没有 glob 限定符,也没有任何接口readlink()(如内置zshstat),但在某些系统上,您会找到一个readlink命令:

$ readlink a
b

相关内容