Wie liste ich symbolische Gliederketten auf?

36

In diesem Beispiel:

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

Wenn ich ausführe:

ls -l d

Wird sich zeigen:

d -> c

Gibt es eine Möglichkeit ls, d -> c -> b -> astattdessen einen anderen Linux-Befehl anzuzeigen ?

Kalecser
quelle
Ich kreuze dies als stackoverflow.com/questions/2320277/… gepostet. Ich hoffe, es macht Ihnen nichts aus.
Paul,

Antworten:

65

Verwenden Sie einfach namei:

$ namei d
f: d
 l d -> c
   l c -> b
     l b -> a
       d a
Mike
quelle
5
Bis. Das ist ein cooler Befehl. Upvotes
Tom O'Connor
Dies sollte die akzeptierte Antwort sein, da sie die gesamte Kette von Links zeigt, wie sie in der Operation angefordert wurden. Außerdem kann es verwendet werden, um ein ganzes Verzeichnis ähnlich dem aufzulisten ls. Vielen Dank!
phobische
In der Tat war dieses Posting erneut und namei ist ein wunderbarer Befehl!
Kalecser
Verwenden Sie den Befehl "which", um die tatsächliche Verwendung eines Programms zu ermitteln: $ namei `which java`
pdem
18

readlink -e <link>

readlink [OPTION] ... DATEI

  • -e, --canonicalize-existing
    canonicalize, indem rekursiv jedem Symlink in jeder Komponente des angegebenen Namens gefolgt wird, müssen alle Komponenten existieren
$ 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

Hinweis: readlink a selbst gibt b zurück

note # 2: zusammen mit find -l kann ein Dienstprogramm zum Auflisten der Ketten leicht in Perl geschrieben werden, muss aber auch intelligent genug sein, um Schleifen zu erkennen

readlink gibt nichts aus, wenn Sie eine Schleife haben. Das ist wohl besser als stecken zu bleiben.

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)
Paul
quelle
Unter OS X: brew install coreutilsundgreadlink -e <link>
Jose Alban
3

Hier ist eine rekursive Funktion 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; }

In mehreren Zeilen:

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
}

Beispiele:

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

Es erfordert, stat(1)die auf einigen Systemen möglicherweise nicht vorhanden sind.

Es schlägt fehl, wenn Namen Backticks, einfache Anführungszeichen oder "->" enthalten. Es bleibt in einer Schleife mit Symlink-Schleifen stecken (dies könnte mit einem assoziativen Array in Bash 4 gelöst werden). Es exportiert eine Variable namens "chain", unabhängig davon, ob sie bereits verwendet wird.

Es kann andere Probleme damit geben.

Bearbeiten:

Ein Problem mit einigen relativen Symlinks wurde behoben. Einige funktionieren immer noch nicht, aber für die folgende Version muss das Ziel des Links nicht vorhanden sein.

Es wurde eine Version hinzugefügt, die readlink verwendet:

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
}
Bis auf weiteres angehalten.
quelle
Ich habe Ihr Skript getestet und es funktioniert wirklich, aber ich bevorzuge etwas Einfacheres, also habe ich die andere Antwort akzeptiert, auch wenn sie unvollständig ist.
Kalecser
1
Nettes Drehbuch. Manchmal möchte ich die gesamte Kette sehen und readlinkscheint das nicht zu zeigen. Java auf Ubuntu ist:/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java
Stefan Lasiewski
0

Sie könnten die Ausgabe von namei einfach mit etwas wie awkoder nachbearbeiten grep, um nur die gewünschten Zeilen zu erhalten:

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

oder

namei d | egrep -e "->"
Tony
quelle