如何递归地获取链接的`ls -l` 输出,直到到达原始文件?

Pan*_*dya 6 ls shell-script symlink

让我举个例子(这只是从这里取的一个例子):

$ ls -l /usr/bin/gnome-text-editor 
lrwxrwxrwx 1 root root 35 Mar 16  2015 /usr/bin/gnome-text-editor -> /etc/alternatives/gnome-text-editor
$ ls -l /etc/alternatives/gnome-text-editor
lrwxrwxrwx 1 root root 14 Mar 16  2015 /etc/alternatives/gnome-text-editor -> /usr/bin/gedit
$ ls -l /usr/bin/gedit
-rwxr-xr-x 1 root root 588064 Mar 27  2014 /usr/bin/gedit
Run Code Online (Sandbox Code Playgroud)

在这里您可以看到,我必须使用ls -l3 次才能到达目的地。(第三次是为了确保这/usr/bin/gedit不是链接`)

有什么方法(通过制作脚本或其他命令等)可以获得预期的输出,例如:

$ <improved ls -l> /usr/bin/gnome-text-editor 
lrwxrwxrwx 1 root root 35 Mar 16  2015 /usr/bin/gnome-text-editor -> /etc/alternatives/gnome-text-editor
lrwxrwxrwx 1 root root 14 Mar 16  2015 /etc/alternatives/gnome-text-editor -> /usr/bin/gedit
Run Code Online (Sandbox Code Playgroud)

另一个好的输出可能是:

$ <some-command> /usr/bin/gnome-text-editor
/usr/bin/gnome-text-editor > /etc/alternatives/gnome-text-editor > /usr/bin/gedit
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 12

在这种情况下,这是 Debian 的“替代方案”,因此要获得更多详细信息,您可以使用:

$ update-alternatives --display gnome-text-editor
gnome-text-editor - auto mode
  link best version is /usr/bin/gedit
  link currently points to /usr/bin/gedit
  link gnome-text-editor is /usr/bin/gnome-text-editor
  slave gnome-text-editor.1.gz is /usr/share/man/man1/gnome-text-editor.1.gz
/usr/bin/gedit - priority 50
  slave gnome-text-editor.1.gz: /usr/share/man/man1/gedit.1.gz
/usr/bin/leafpad - priority 40
  slave gnome-text-editor.1.gz: /usr/share/man/man1/leafpad.1.gz
Run Code Online (Sandbox Code Playgroud)

更一般地,在 Linux 上,您可以使用该namei命令了解路径解析中涉及的所有符号链接(也可以使用 挂载点-x):

$ namei -lx /usr/bin/gnome-text-editor
f: /usr/bin/gnome-text-editor
Drwxr-xr-x root root /
drwxr-xr-x root root usr
drwxr-xr-x root root bin
lrwxrwxrwx root root gnome-text-editor -> /etc/alternatives/gnome-text-editor
Drwxr-xr-x root root   /
drwxr-xr-x root root   etc
drwxr-xr-x root root   alternatives
lrwxrwxrwx root root   gnome-text-editor -> /usr/bin/gedit
Drwxr-xr-x root root     /
drwxr-xr-x root root     usr
drwxr-xr-x root root     bin
-rwxr-xr-x root root     gedit
Run Code Online (Sandbox Code Playgroud)

为了更直接地回答您的问题,我会执行以下操作:

#! /bin/zsh -
zmodload zsh/stat || exit
ret=0
for file do
  n=0
  while
    ls -ld -- "$file" || ! ret=1 && [ -L "$file" ]
  do
    if ((++n > 40)) && [ ! -e "$file" ]; then
      echo >&2 too many symlinks
      ret=1
      break
    fi
    zstat -A target +link -- "$file" || ! ret=1 || break
    case $target in
      (/*) file=$target;;
      (*)  file=$file:h/$target
    esac
  done
done
exit "$ret"
Run Code Online (Sandbox Code Playgroud)

这可能无法为您提供了解正在发生的事情所需的所有信息。比较例如:

$ ./resolve-symlink b/b/b/b/x/b
lrwxrwxrwx 1 stephane stephane 1 Mar 18 15:37 b/b/b/b/x/b -> a
lrwxrwxrwx 1 stephane stephane 4 Mar 18 15:37 b/b/b/b/x/a -> ../a
lrwxrwxrwx 1 stephane stephane 26 Mar 18 15:15 b/b/b/b/x/../a -> /usr/bin/gnome-text-editor
lrwxrwxrwx 1 root root 35 Nov  5  2013 /usr/bin/gnome-text-editor -> /etc/alternatives/gnome-text-editor
lrwxrwxrwx 1 root root 14 Mar 15 12:21 /etc/alternatives/gnome-text-editor -> /usr/bin/gedit
-rwxr-xr-x 1 root root 10344 Nov 12 17:18 /usr/bin/gedit
Run Code Online (Sandbox Code Playgroud)

和:

$ namei -lx b/b/b/b/x/b
f: b/b/b/b/x/b
lrwxrwxrwx stephane stephane b -> .
drwxr-xr-x stephane stephane   .
lrwxrwxrwx stephane stephane b -> .
drwxr-xr-x stephane stephane   .
lrwxrwxrwx stephane stephane b -> .
drwxr-xr-x stephane stephane   .
lrwxrwxrwx stephane stephane b -> .
drwxr-xr-x stephane stephane   .
lrwxrwxrwx stephane stephane x -> 2
drwxr-xr-x stephane stephane   2
lrwxrwxrwx stephane stephane b -> a
lrwxrwxrwx stephane stephane   a -> ../a
drwxr-xr-x stephane stephane     ..
lrwxrwxrwx stephane stephane     a -> /usr/bin/gnome-text-editor
Drwxr-xr-x root     root           /
drwxr-xr-x root     root           usr
drwxr-xr-x root     root           bin
lrwxrwxrwx root     root           gnome-text-editor -> /etc/alternatives/gnome-text-editor
Drwxr-xr-x root     root             /
drwxr-xr-x root     root             etc
drwxr-xr-x root     root             alternatives
lrwxrwxrwx root     root             gnome-text-editor -> /usr/bin/gedit
Drwxr-xr-x root     root               /
drwxr-xr-x root     root               usr
drwxr-xr-x root     root               bin
-rwxr-xr-x root     root               gedit
Run Code Online (Sandbox Code Playgroud)


小智 10

readlink 是您正在寻找的命令。

$ readlink -e /usr/bin/gnome-text-editor
/usr/bin/gedit
Run Code Online (Sandbox Code Playgroud)

根据您在链接断开时的行为方式,可以使用各种标志 ( -f, -e, -m) -man readlink有关详细信息,请参阅。


Pan*_*dya 2

您可以使用以下脚本:

$ cat myll
#!/bin/bash
name="$1"
while [[ -L "$name" ]]; do
ls -l "$name"; 
name=`readlink "$name"`;
done
Run Code Online (Sandbox Code Playgroud)

输出示例:

$ myll /usr/bin/gnome-text-editor
lrwxrwxrwx 1 root root 35 Mar 16  2015 /usr/bin/gnome-text-editor -> /etc/alternatives/gnome-text-editor
lrwxrwxrwx 1 root root 14 Mar 16  2015 /etc/alternatives/gnome-text-editor -> /usr/bin/gedit
Run Code Online (Sandbox Code Playgroud)

这里[[ -L "$name" ]]检查文件是否是链接并readlink "$name"读取链接并将其保存到变量中name以供下一个循环使用。因此while [[ -L "$name" ]]循环直到到达原始目标/文件。


对于第二种解决方法,您可以使用:

#!/bin/bash
name="$1"
while [[ -L "$name" ]]; do
echo -n "$name > ";
name=`readlink "$name"`;
done
echo "$name"
Run Code Online (Sandbox Code Playgroud)

输出示例:

$ myls /usr/bin/gnome-text-editor
/usr/bin/gnome-text-editor > /etc/alternatives/gnome-text-editor > /usr/bin/gedit
Run Code Online (Sandbox Code Playgroud)

  • 这对于相对符号链接无法正常工作(因为相对符号链接是相对于符号链接的主机目录,而不是相对于当前工作目录)。 (2认同)