This recursive Bash function will print the link chain and count plus the diagnostic:
chain() { local link target; if [[ -z $_chain ]]; then unset _chain_count _expansion; _chain="$1"; fi; link=$(stat --printf=%N $1); while [[ $link =~ \-\> ]]; do target="${link##*\`}"; target="${target%\'}"; _chain+=" -> $target"; ((_chain_count++)); _expansion+="$_chain_count. $1 is expanded to $target $(stat --printf="(%A %U %G)" $target)"$'\n'; chain "$target"; return; done; echo "$_chain ($_chain_count)"; echo "$_expansion"; unset _chain _chain_count _expansion; }
It requires stat
. For more information and a version that uses readlink
instead of stat
, see my answer here (the count feature would need to be added but adding the permissions and owner/group would be a little more challenging).
For this:
a
b -> a
c -> b
d -> c
The output of chain d
would be:
d -> c -> b -> a (3)
1. d is expanded to c (lrwxrwxrwx username groupname)
2. c is expanded to b (lrwxrwxrwx username groupname)
3. b is expanded to a (-rw-r--r-- root root)
Here is a more readable version of the function:
chain ()
{
local link target;
if [[ -z $_chain ]]; then
unset _chain_count _expansion;
_chain="$1";
fi;
link=$(stat --printf=%N $1);
while [[ $link =~ \-\> ]]; do
target="${link##*\`}";
target="${target%\'}";
_chain+=" -> $target";
((_chain_count++));
_expansion+="$_chain_count. $1 is expanded to $target $(stat --printf="(%A %U %G)" $target)"$'\n';
chain "$target";
return;
done;
echo "$_chain ($_chain_count)";
echo "$_expansion";
unset _chain _chain_count _expansion
}