Soluzione 1:
Basta usare namei :
$ namei d
f: d
l d -> c
l c -> b
l b -> a
d a
Soluzione 2:
readlink -e <link>
readlink [OPZIONE]... FILE
- -e, --canonicalize-esistente
canonicalize seguendo ogni collegamento simbolico in ogni componente del nome dato in modo ricorsivo, tutti i componenti devono esistere
$ mkdir testlink
$ cd testlink
example@unixlinux.online:~/testlink$ ln -s c b
example@unixlinux.online:~/testlink$ ln -s b a
example@unixlinux.online:~/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
example@unixlinux.online:~/testlink$ echo foo > c
example@unixlinux.online:~/testlink$ cat a
foo
example@unixlinux.online:~/testlink$ readlink -e a
/home/pjb/testlink/c
nota:readlink a da solo restituisce b
nota #2:insieme a find -l, un'utilità per elencare le catene potrebbe essere facilmente scritta in perl, ma deve anche essere abbastanza intelligente da rilevare i loop
readlink non produrrà nulla se hai un ciclo. Questo è meglio che rimanere bloccati, suppongo.
example@unixlinux.online:~/testlink$ ln -sf a c
example@unixlinux.online:~/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
example@unixlinux.online:~/testlink$ readlink -e a
example@unixlinux.online:~/testlink$ # (note: no output)
Soluzione 3:
Ecco una funzione ricorsiva in Bash:
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; }
Su più righe:
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
}
Esempi:
$ chain d
d -> c -> b -> a
$ chain c
c -> b -> a
$ chain a
a
Richiede stat(1) che potrebbe non essere presente su alcuni sistemi.
Fallirà se i nomi contengono apici inversi, virgolette singole o "->". Si blocca in un ciclo con cicli di collegamenti simbolici (questo potrebbe essere risolto utilizzando un array associativo in Bash 4). Esporta una variabile chiamata "chain" indipendentemente dal fatto che sia già in uso.
Potrebbero esserci altri problemi con esso.
Modifica:
Risolto un problema con alcuni collegamenti simbolici relativi. Alcuni continuano a non funzionare, ma la versione seguente non richiede l'esistenza della destinazione del collegamento.
Aggiunta una versione che utilizza 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
}