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

11 浏览
0 Comments

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

找到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

0
0 Comments

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

在GNU/Linux中,除了使用readlink命令外,用户还可以使用来自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

很棒的东西;看起来namei在许多发行版上都预装了,并且可以列出其他信息,例如模式位。我希望它能解析相对目标路径为绝对路径;如果没有它,有时很难确定指的是哪个路径,特别是带有..组件的情况。

0
0 Comments

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

有时候我们可能需要查看一个符号链接链中的所有成员,以了解符号链接是如何链接到最终目标的。下面是几种解决这个问题的方法:

1. 使用typex工具:typex是一个使用绝对路径打印给定路径的符号链接链的工具。它可以通过以下命令进行安装:

npm install typex -g

使用示例:

$ typex awk
BINARY:  /usr/bin/awk@ -> /etc/alternatives/awk@ -> /usr/bin/gawk  [GNU Awk 4.0.1]

2. 使用rreadlink工具:rreadlink是一个更底层的工具,可以打印任何给定文件系统路径的符号链接链。它可以通过以下命令进行安装:

npm install rreadlink -g

使用示例:

$ rreadlink -1 "$(which awk)"
/usr/bin/awk
/etc/alternatives/awk
/usr/bin/gawk

3. 使用rreadlinkchain函数:rreadlinkchain是一个完全符合POSIX标准的脚本/函数,只使用POSIX shell语言特性和符合POSIX标准的工具调用。它可以递归地打印符号链接链的每一步的绝对路径,直到最终目标。以下是rreadlinkchain函数的代码:

#!/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 "$@"

这些方法都可以在多个平台上使用,并提供了对符号链接链的详细输出。

0
0 Comments

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

考虑安装“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

软件包描述:

包:chase

状态:已安装

自动安装:否

版本:0.5.2-4build2

优先级:可选项

部分:universe/utils

维护者:Ubuntu Developers

构架:amd64

未压缩大小:61.4 k

依赖项:libc6(>= 2.3.4),libgc1c2(>= 1:7.2d)

冲突:chase

描述:跟踪符号链接并打印其目标文件

Chase是一个用于追踪符号链接指向的实际文件的小型实用程序-追踪符号链接。成功运行的结果保证是一个存在的文件,而不是一个符号链接。

好好知道,也很高兴看到“chase”具有符号链接循环检测。与“namei”不同,“chase”令人称赞地始终将最终的目标路径作为绝对路径打印出来,但我希望它也能对中间的路径进行同样的操作,这些路径的目标被定义为相对路径(可能还包括相对路径),因为并不总是明显指的是哪个路径,特别是使用“..”。

0