如何列出符号链的所有成员?

时间:2015-10-21 09:22:50

标签: bash symlink symlink-traversal

查找java二进制文件可能很痛苦:

  • which java提供/usr/bin/java
  • lh $(which java)提供/usr/bin/java -> /etc/alternatives/java
  • lh /etc/alternatives/java提供/etc/alternatives/java -> /usr/lib/jvm/jdk1.8.0_66/bin/java

有没有办法自动关注符号链并打印所有成员?例如whichfollowfollow /usr/bin/java可以提供:

/usr/bin/java
-> /etc/alternatives/java
-> /usr/lib/jvm/jdk1.8.0_66/bin/java

4 个答案:

答案 0 :(得分:6)

readlink命令外,GNU / Linux用户还可以使用util-linux包中的namei命令。根据其手册页:

  

namei使用其参数作为任何类型的Unix文件(符号链接,文件,目录等)的路径名。然后,namei跟随每个路径名,直到找到一个端点(文件,目录,设备节点等)。如果找到符号链接,它会显示该链接,并开始跟随它,缩进输出以显示上下文。

它的输出并不像你想的那样漂亮,但它显示了每条路径 组件和节目,如果它是一个目录,符号链接,套接字,块设备,字符设备,FIFO(命名管道)或常规文件。

使用示例:

$ namei  /usr/bin/java

f: /usr/bin/java
 d /
 d usr
 d bin
 l java -> /etc/alternatives/java
   d /
   d etc
   d alternatives
   l java -> /usr/lib/jvm/jre-1.7.0-openjdk/bin/java
     d /
     d usr
     d lib
     d jvm
     l jre-1.7.0-openjdk -> java-1.7.0-openjdk-1.7.0.85/jre
       d java-1.7.0-openjdk-1.7.0.85
       d jre
     d bin
     - java

答案 1 :(得分:4)

注意:namei(请参阅Anthony Geoghegan's answer)和chase(请参阅Toby Speight's answer)是非常棒的 Linux 选项;这个答案提供:
* 跨平台解决方案
*打印链的每个步骤的绝对路径,即使符号链接是用相对路径定义的。

  • 考虑 typex utility (由我编写),使用绝对路径打印$PATH中给定实用程序的符号链。在每一步中(typex还提供了额外的信息,类似于type,但比npm install typex -g更广泛。
    • 安装了Node.js的最简单安装:--version
    • 示例(请注意如何附加使用java获取的版本信息 - 不适用于-version,但使用 $ typex awk BINARY: /usr/bin/awk@ -> /etc/alternatives/awk@ -> /usr/bin/gawk [GNU Awk 4.0.1] ):
npm install rreadlink -g
  • rreadlink 是一个较低级别的实用程序(由我编写),它将符号链接打印为任何给定文件系统路径的绝对路径。

    • 安装了Node.js的最简单安装:$ rreadlink -1 "$(which awk)" /usr/bin/awk /etc/alternatives/awk /usr/bin/gawk
    • 示例:

      rreadlinkchain()
  • 以下是bash完全符合POSIX标准的脚本/功能 - 它仅使用POSIX shell language features且仅使用符合POSIX的实用程序调用。它是上面两个实用程序核心的rreadlinkchain "$(which java)"函数的POSIX兼容变体,并且很感激地从this answer改编而来;适用于您的示例:typex

兼容性说明:
从npm注册表安装时,rreadlinkbash支持 OS X和Linux ,但可能也会在rreadlinkchain()的BSD系统上运行,手动安装时 如上所述,下面的#!/bin/sh ## ------- # SYNOPSIS # rreadlinkchain <symLink> # DESCRIPTION # Recursive readlink: prints the CHAIN OF SYMLINKS from the input # file to its ultimate target, as ABSOLUTE paths, with each path on a separate # line. # Only the ultimate target's path is canonical, though. # A broken symlink in the chain causes an error that reports the # non-existent target. # An input path that is not a symlink will print its own canonical path. # LIMITATIONS # - Won't work with filenames with embedded newlines or filenames containing # the string ' -> '. # COMPATIBILITY # Fully POSIX-compliant. # EXAMPLES # # Print the symlink chain of the `git` executable in the $PATH. # rreadlinkchain "$(which git)" # # Ditto, using single-line `ls -l`-style format ('a@ -> b') # rreadlinkchain "$(which git)" | sed -nE -e '$!{a\'$'\n''@ -> ' -e '}; p' | tr -d '\n' # THANKS # https://stackoverflow.com/a/1116890/45375 rreadlinkchain() ( # execute in *subshell* to localize the effect of `cd`, ... target=$1 targetDir= targetName= CDPATH= # Try to make the execution environment as predictable as possible: # All commands below are invoked via `command`, so we must make sure that # `command` itself is not redefined as an alias or shell function. # (Note that command is too inconsistent across shells, so we don't use it.) # `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not # even have an external utility version of it (e.g, Ubuntu). # `command` bypasses aliases and shell functions and also finds builtins # in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for # that to happen. { \unalias command; \unset -f command; } >/dev/null 2>&1 [ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too. while :; do # Unless the file is a symlink OR exists, we report an error - note that using `-e` with a symlink reports the *target*'s existence, not the symlink's. [ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." 1>&2; return 1; } # !! We use `cd` to change to the target's folder # !! so we can correctly resolve the full dir. path. command cd "$(command dirname -- "$target")" # note: cd "" is the same as cd . - i.e., a no-op. targetDir=$PWD targetName=$(command basename -- "$target") [ "$targetName" = '/' ] && targetName='' # !! curiously, `basename /` returns '/' done=0 if [ ! -L "$targetName" ]; then # We've found the ultimate target (or the input file wasn't a symlink to begin with). # For the *ultimate* target we want use `pwd -P` to make sure we use the actual, physical directory, # (not a symlink) to get the *canonical* path. targetDir=$(command pwd -P) done=1 fi # Print (next) path - note that we manually resolve paths ending # in /. and /.. to make sure we have a normalized path. if [ "$targetName" = '.' ]; then command printf '%s\n' "${targetDir%/}" elif [ "$targetName" = '..' ]; then # Caveat: something like /var/.. will resolve to /private (assuming # /var@ -> /private/var), i.e. the '..' is applied AFTER canonicalization. command printf '%s\n' "$(command dirname -- "${targetDir}")" else command printf '%s\n' "${targetDir%/}/$targetName" fi # Exit, if we've hit the non-symlink at the end of the chain. [ "$done" = 1 ] && break # File is symlink -> continue to resolve. # Parse `ls -l` output, which, unfortunately, is the only POSIX-compliant # way to determine a symlink's target. Hypothetically, this can break with # filenames containig literal ' -> ' and embedded newlines. target=$(command ls -l -- "$targetName") target=${target#* -> } done ) rreadlinkchain "$@" 函数完全符合POSIX标准,并且可以在大多数类Unix平台上运行。 功能

<span>10 000,00</span>
<span class="currency">€</span>

答案 2 :(得分:1)

您可以将whilefunction follow { path="$1" echo "$path" while path=$(readlink "$path"); do echo "-> $path" done } follow "/usr/bin/java" 循环一起使用。以下功能可行:

libusb_detach_kernel_driver

答案 3 :(得分:1)

考虑安装chase

示例输出:

$ chase --verbose /usr/bin/java
/usr/bin/java
-> /etc/alternatives/java
-> /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java
/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java

包装说明:

套餐:追逐
状态:已安装 自动安装:没有 版本:0.5.2-4build2
优先级:可选
部分:universe / utils
维护者:Ubuntu开发人员
架构:amd64
未压缩尺寸:61.4 k
取决于:libc6(&gt; = 2.3.4),libgc1c2(&gt; = 1:7.2d)
冲突:追逐
说明:按照符号链接打印出目标文件
 Chase是一个小实用程序,用于跟踪a的实际文件  符号链接指向 - 追逐符号链接,如果你愿意的话。该  成功运行的结果保证是现有文件  不是象征性的联系。