Jak wyświetlić symboliczne łańcuchy linków?

36

Biorąc pod uwagę ten przykład:

mkdir a
ln -s a b
ln -s b c
ln -s c d

Jeśli wykonam:

ls -l d

Pokaże:

d -> c

Czy istnieje sposób lslub inne polecenie linux, aby pokazać d -> c -> b -> azamiast tego?

Kalecser
źródło
Przekazałem to jako stackoverflow.com/questions/2320277/... Mam nadzieję, że nie masz nic przeciwko.
Paul

Odpowiedzi:

65

Po prostu użyj namei:

$ namei d
f: d
 l d -> c
   l c -> b
     l b -> a
       d a
Mikrofon
źródło
5
TIL To fajne polecenie. głosy poparcia
Tom O'Connor
To powinna być zaakceptowana odpowiedź, ponieważ pokazuje pełny łańcuch linków zgodnie z żądaniem w op. Ponadto można go użyć do wyświetlenia całego katalogu podobnego do ls. Dzięki!
fobiczny
Rzeczywiście, przeglądałem ten post, a namei to wspaniałe polecenie!
Kalecser
użyj z komendą „która”, aby znaleźć faktyczne użycie programu: $ namei `which java`
pdem
18

readlink -e <link>

readlink [OPCJA] ... PLIK

  • -e, --canonicalize-Istniejące kanonizowanie
    poprzez rekursywne śledzenie każdego dowiązania symbolicznego w każdym komponencie podaną nazwą, wszystkie komponenty muszą istnieć
$ mkdir testlink
$ cd testlink
pjb@pjb-desktop:~/testlink$ ln -s c b
pjb@pjb-desktop:~/testlink$ ln -s b a
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 -e a
/home/pjb/testlink/c

Uwaga: readlink a sam w sobie zwraca b

uwaga # 2: wraz z find -l narzędzie do listy łańcuchów może być łatwo napisane w perlu, ale musi być również wystarczająco inteligentne, aby wykrywać pętle

readlink nic nie wyświetli, jeśli masz pętlę. To chyba lepsze niż utknięcie.

pjb@pjb-desktop:~/testlink$ ln -sf a c
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 -e a
pjb@pjb-desktop:~/testlink$ # (note: no output)
Paweł
źródło
W systemie OS X: brew install coreutilsigreadlink -e <link>
Jose Alban
3

Oto funkcja rekurencyjna w 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; }

Na wielu liniach:

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
}

Przykłady:

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

Wymaga tego, stat(1)co może nie być obecne w niektórych systemach.

Nie powiedzie się, jeśli nazwy zawierają znaki wsteczne, pojedyncze cudzysłowy lub „->”. Utknie w pętli z pętlami dowiązań symbolicznych (można to rozwiązać za pomocą tablicy asocjacyjnej w Bash 4). Eksportuje zmienną zwaną „łańcuchem” bez względu na to, czy jest już używana.

Mogą być z tym inne problemy.

Edytować:

Naprawiono problem z niektórymi względnymi dowiązaniami symbolicznymi. Niektóre nadal nie działają, ale wersja poniżej nie wymaga istnienia celu linku.

Dodano wersję, która wykorzystuje 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
}
Wstrzymano do odwołania.
źródło
Przetestowałem twój skrypt i naprawdę działa, ale wolę coś prostszego, więc zaakceptowałem inną odpowiedź, nawet jeśli jest niekompletna.
Kalecser
1
Niezły scenariusz. Czasami chcę zobaczyć cały łańcuch i readlinkwydaje mi się, że tego nie pokazuje. Java na Ubuntu to:/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java
Stefan Lasiewski
0

Możesz po prostu przetworzyć dane wyjściowe namei za pomocą czegoś podobnego awklub grepuzyskać tylko potrzebne linie:

namei d | awk '$1=="l"'

lub

namei d | egrep -e "->"
Tony
źródło