Как составить список цепочек символических ссылок?

36

Учитывая этот пример:

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

Если я выполню:

ls -l d

Это покажет:

d -> c

Есть ли способ lsили любая другая команда Linux, чтобы показать d -> c -> b -> aвместо этого?

Kalecser
источник
Я опубликовал это как stackoverflow.com/questions/2320277/… Надеюсь, вы не против.
Пол

Ответы:

65

Просто используйте namei:

$ namei d
f: d
 l d -> c
   l c -> b
     l b -> a
       d a
Майк
источник
5
TIL. Это классная команда. upvotes
Том О'Коннор
Это должен быть принятый ответ, так как он показывает полную цепочку ссылок, как было запрошено в оп. Кроме того, он может быть использован для перечисления всего каталога, похожего на ls. Благодарность!
фобический
Действительно, пересматривал этот пост, и Namei - замечательная команда!
Kalecser
используйте команду "which", чтобы найти фактическое использование программы: $ namei `which java`
pdem
18

readlink -e <link>

readlink [ОПЦИЯ] ... ФАЙЛ

  • -e, --canonicalize-существующие
    canonicalize путем рекурсивного следования каждой символической ссылке в каждом компоненте данного имени, все компоненты должны существовать
$ 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

примечание: readlink a само по себе возвращает b

примечание # 2: вместе с find -l утилита для перечисления цепочек может быть легко написана на perl, но также должна быть достаточно умной для обнаружения циклов

readlink не будет ничего выводить, если у вас есть цикл. Полагаю, это лучше, чем застрять.

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)
Павел
источник
На OS X: brew install coreutilsиgreadlink -e <link>
Хосе Албан
3

Вот рекурсивная функция в 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; }

На нескольких строках:

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
}

Примеры:

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

Требуется, stat(1)что может не присутствовать в некоторых системах.

Это не удастся, если имена содержат обратные кавычки, одинарные кавычки или "->". Он застревает в цикле с циклами символических ссылок (это можно решить с помощью ассоциативного массива в Bash 4). Он экспортирует переменную под названием «цепочка», независимо от того, используется ли она уже.

Могут быть другие проблемы с этим.

Редактировать:

Исправлена ​​проблема с некоторыми относительными символическими ссылками. Некоторые все еще не работают, но версия ниже не требует, чтобы цель ссылки существовала.

Добавлена ​​версия, которая использует 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
}
Приостановлено до дальнейшего уведомления.
источник
Я проверил ваш сценарий, и он действительно работает, но я предпочитаю что-то более простое, поэтому я принял другой ответ, даже если он неполный.
Kalecser
1
Хороший сценарий. Иногда я хочу увидеть всю цепочку, и readlink, похоже , это не показывает. Java на Ubuntu - это:/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java
Стефан Ласевский
0

Вы можете просто обработать вывод namei чем-то вроде awkили grepполучить строки, которые вы хотите:

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

или

namei d | egrep -e "->"
Тони
источник