鉴于这个例子:
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 }