¿Cómo enumerar cadenas de enlaces simbólicos?


Respuestas:


65

Solo usa namei:

$ namei d
f: d
 l d -> c
   l c -> b
     l b -> a
       d a

55
TIL Este es un comando genial . votos a favor
Tom O'Connor

Esta debería ser la respuesta aceptada, ya que muestra la cadena completa de enlaces según lo solicitado en el op. Además, se puede utilizar para enumerar un directorio completo similar a ls. ¡Gracias!
fóbico

De hecho, estaba revisando esta publicación y namei es un comando maravilloso.
Kalecser

use con el comando "which" para encontrar el uso real de un programa: $ namei `which java`
pdem

18

readlink -e <link>

readlink [OPCIÓN] ... ARCHIVO

  • -e, --canonicalize-
    canonicalize existente siguiendo cada enlace simbólico en cada componente del nombre dado de forma recursiva, todos los componentes deben existir
$ 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

nota: readlink a por sí mismo devuelve b

nota # 2: junto con find -l, una utilidad para enumerar las cadenas podría escribirse fácilmente en perl, pero también debe ser lo suficientemente inteligente como para detectar bucles

readlink no generará nada si tiene un bucle. Esto es mejor que quedarse atascado, supongo.

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)

En OS X: brew install coreutilsygreadlink -e <link>
Jose Alban

3

Aquí hay una función recursiva en 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; }

En múltiples líneas:

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
}

Ejemplos:

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

Requiere stat(1)que puede no estar presente en algunos sistemas.

Fallará si los nombres contienen backticks, comillas simples o "->". Se atasca en un bucle con bucles de enlace simbólico (esto podría resolverse usando una matriz asociativa en Bash 4). Exporta una variable llamada "cadena" sin importar si ya está en uso.

Puede haber otros problemas con esto.

Editar:

Se solucionó un problema con algunos enlaces simbólicos relativos. Algunos todavía no funcionan, pero la versión a continuación no requiere que exista el objetivo del enlace.

Se agregó una versión que usa 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
}

He probado su script y realmente funciona, pero prefiero algo más simple, así que he aceptado la otra respuesta, incluso si está incompleta.
Kalecser

1
Buen guión. A veces quiero ver toda la cadena, y readlinkno parece mostrar eso. Java en Ubuntu es:/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java
Stefan Lasiewski

0

Podrías simplemente postprocesar la salida de namei con algo como awku grepobtener las líneas que deseas:

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

o

namei d | egrep -e "->"
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.