如何列出符号链接链?

鉴于这个例子:

mkdir a ln -sab ln -sbc ln -scd 

如果我执行:

 ls -ld 

它会显示:

 d -> c 

有没有办法使用ls或其他的linux命令来显示d -> c -> b -> a来代替?

只需使用namei

 $ namei d f: d ld -> c lc -> b lb -> a da 

readlink -e <link>

readlink [选项] …文件

  • -e,–canonicalize-existing
    通过recursion地跟踪给定名称的每个组件中的每个符号链接来规范化,所有组件必须存在
 $ mkdir testlink $ cd testlink pjb@pjb-desktop:~/testlink$ ln -scb pjb@pjb-desktop:~/testlink$ ln -sba pjb@pjb-desktop:~/testlink$ ls -l total 0 lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c pjb@pjb-desktop:~/testlink$ echo foo > c pjb@pjb-desktop:~/testlink$ cat a foo pjb@pjb-desktop:~/testlink$ readlink -ea /home/pjb/testlink/c 

注意:readlink a本身返回b

注意#2:与find -l一起,列出链的实用程序可以很容易地用Perl编写,但是也必须足够聪明以检测循环

如果你有一个循环,readlink将不会输出任何东西。 我想这比卡住要好。

 pjb@pjb-desktop:~/testlink$ ln -sf ac pjb@pjb-desktop:~/testlink$ ls -l total 0 lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:03 c -> a pjb@pjb-desktop:~/testlink$ readlink -ea pjb@pjb-desktop:~/testlink$ # (note: no output) 

这里是Bash的recursion函数:

 chain() { export chain; local link target; if [[ -z $chain ]]; then chain="$1"; fi; link=$(stat --printf=%N $1); while [[ $link =~ \-\> ]]; do target="${link##*\`}"; target="${target%\'}"; chain+=" -> $target"; chain "$target"; return; done; echo "$chain"; unset chain; } 

在多行上:

 chain() { export chain local link target if [[ -z $chain ]] then chain="$1" fi link=$(stat --printf=%N "$1") while [[ $link =~ \-\> ]] do target="${link##*\`}" target="${target%\'}" chain+=" -> $target" if [[ ! $target =~ / && $1 =~ / ]] then target="${1%/*}/$target" fi chain "$target" return done echo "$chain" unset chain } 

例子:

 $ chain d d -> c -> b -> a $ chain c c -> b -> a $ chain a a 

它需要stat(1) ,在某些系统上可能不存在。

如果名称包含反引号,单引号或“ – >”,则会失败。 它陷入了一个符号链接循环(这可以使用Bash 4中的关联数组来解决)。 它输出一个名为“chain”的variables,而不考虑它是否已被使用。

可能还有其他问题。

编辑:

修复了一些相关符号链接的问题。 有些仍然不起作用,但下面的版本并不要求链接的目标存在。

增加了一个使用readlink的版本:

 chain () { export chain; local target; if [[ -z $chain ]]; then chain="$1"; fi; target=$(readlink "$1"); while [[ $target ]]; do chain+=" -> $target"; if [[ ! $target =~ / && $1 =~ / ]] then target="${1%/*}/$target" fi chain "$target"; return; done; echo "$chain"; unset chain }