Comment lister les chaînes de liens symboliques?

36

Étant donné cet exemple:

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

Si j'exécute:

ls -l d

Il montrera:

d -> c

Existe-t-il un moyen pour lsou toute autre commande linux d'afficher à la d -> c -> b -> aplace?

Kalecser
la source
Je vous ai posté ceci sous le nom stackoverflow.com/questions/2320277/… J'espère que cela ne vous dérange pas.
Paul

Réponses:

65

Il suffit d'utiliser namei:

$ namei d
f: d
 l d -> c
   l c -> b
     l b -> a
       d a
Mike
la source
5
TIL. C'est une commande cool . upvotes
Tom O'Connor
Cela devrait être la réponse acceptée, car elle montre la chaîne complète de liens comme demandé dans l'op. En outre, il peut être utilisé pour répertorier un répertoire entier similaire à ls. Merci!
phobique
En effet, revisiterais ce post et namei est une commande merveilleuse!
Kalecser
utilisez la commande "which" pour trouver l'utilisation réelle d'un programme: $ namei `which java`
pdem
18

readlink -e <link>

readlink [OPTION] ... FILE

  • -e, --canonicalize-
    canonicalize existant en suivant chaque lien symbolique dans chaque composant du nom donné de manière récursive, tous les composants doivent exister
$ 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

note: readlink a par lui-même retourne b

note n ° 2: avec find -l, un utilitaire permettant de répertorier les chaînes pourrait facilement être écrit en perl, mais doit également être suffisamment intelligent pour détecter les boucles

readlink ne produira rien si vous avez une boucle. C'est mieux que de rester coincé, je suppose.

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
la source
Sur OS X: brew install coreutilsetgreadlink -e <link>
Jose Alban,
3

Voici une fonction récursive dans 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; }

Sur plusieurs lignes:

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
}

Exemples:

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

Cela nécessite stat(1)ce qui peut ne pas être présent sur certains systèmes.

Il échouera si les noms contiennent des backticks, des guillemets simples ou "->". Il se bloque dans une boucle avec des boucles de liens symboliques (ceci pourrait être résolu en utilisant un tableau associatif dans Bash 4). Il exporte une variable appelée "chaîne", qu'elle soit déjà utilisée ou non.

Il peut y avoir d'autres problèmes avec cela.

Modifier:

Correction d'un problème avec certains liens symboliques relatifs. Certains ne fonctionnent toujours pas, mais la version ci-dessous n'exige pas que la cible du lien existe.

Ajout d'une version qui utilise 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
}
En pause jusqu'à nouvel ordre.
la source
J'ai testé votre script et cela fonctionne vraiment, mais je préfère quelque chose de plus simple, j'ai donc accepté l'autre réponse, même si elle était incomplète.
Kalecser
1
Beau scénario. Parfois, je veux voir toute la chaîne et readlinkne semble pas le montrer. Java sur Ubuntu est:/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java
Stefan Lasiewski
0

Vous pouvez simplement post-traiter la sortie de namei avec quelque chose comme awkou greppour obtenir uniquement les lignes souhaitées:

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

ou

namei d | egrep -e "->"
Tony
la source