3

Например, если символическая ссылка

a -> b
b -> c
c -> d

скажем, уровень символической ссылки а равен 3.

Тогда есть ли утилита для получения этой информации? И также я хочу получить детали расширения символической ссылки, которая покажет мне что-то вроде:

1. /abc/xyz is expanded to /abc/xy/z (lrwx--x--x root root)
2. /abc/xy/z is expanded to /abc/xy-1.3.2/z (lrwx--x--x root root)
3. /abc/xy-1.3.2/z is expanded to /abc/xy-1.3.2/z-4.6 (lrwx--x--x root root)
4. /abc/xy-1.3.2/z-4.6 is expanded to /storage/121/43/z_4_6 (lrwx--x--x root root)
5. /storage/121/43/z_4_6 is expanded to /media/kitty_3135/43/z_4_6 (lrwx--x--x root root)

Так что я могу диагностировать с помощью символических ссылок. Любая идея?

3 ответа3

5

Эта рекурсивная функция Bash напечатает цепочку ссылок и счетчик плюс диагностическое сообщение:

chain() { local link target; if [[ -z $_chain ]]; then unset _chain_count _expansion; _chain="$1"; fi; link=$(stat --printf=%N $1); while [[ $link =~ \-\> ]]; do target="${link##*\`}"; target="${target%\'}"; _chain+=" -> $target"; ((_chain_count++)); _expansion+="$_chain_count. $1 is expanded to $target $(stat --printf="(%A %U %G)" $target)"$'\n'; chain "$target"; return; done; echo "$_chain ($_chain_count)"; echo "$_expansion"; unset _chain _chain_count _expansion; }

Требуется stat . Для получения дополнительной информации и версии, которая использует readlink вместо stat , см. Мой ответ здесь (необходимо было бы добавить функцию подсчета, но добавление полномочий и владельца / группы было бы немного сложнее).

За это:

a
b -> a
c -> b
d -> c

Выход chain d будет:

d -> c -> b -> a (3)
1. d is expanded to c (lrwxrwxrwx username groupname)
2. c is expanded to b (lrwxrwxrwx username groupname)
3. b is expanded to a (-rw-r--r-- root root)

Вот более читаемая версия функции:

chain ()
{
    local link target;
    if [[ -z $_chain ]]; then
        unset _chain_count _expansion;
        _chain="$1";
    fi;
    link=$(stat --printf=%N $1);
    while [[ $link =~ \-\> ]]; do
        target="${link##*\`}";
        target="${target%\'}";
        _chain+=" -> $target";
        ((_chain_count++));
        _expansion+="$_chain_count. $1 is expanded to $target $(stat --printf="(%A %U %G)" $target)"$'\n';
        chain "$target";
        return;
    done;
    echo "$_chain ($_chain_count)";
    echo "$_expansion";
    unset _chain _chain_count _expansion
}
2

Я действительно не знаю о полезности. Вы можете написать это довольно легко. Добавление некоторого вывода stat или ls может дать вам остальную часть пути.

#!/bin/sh

level=0
file=$1
while [ -h "$file" ]
do
    previous="$file"
    file=`readlink "$file"`
    level=$(($level+1))
    echo "$level". "$previous -> $file"
done

Используя это на паре ссылок, установленных в моем homedir, я получаю:

$ ./test.sh link2
1. link2 -> link1
2. link1 -> Test.java
2

В общем, это довольно сложно, так как у вас может быть символическая ссылка, такая как:

ln -s ../symlink/xyz pqr

где «символическая ссылка» сама является символической ссылкой произвольной длины. У меня есть программа, которая выполняет ту же работу, что и realpath() но также проверяет безопасность всех символических ссылок на пути. Таким образом, он может быть использован для ответа на ваш вопрос. И некоторые из его тестовых сценариев могут быть использованы для проверки ваших расчетов.

Это один из таких тестов:

#!/bin/ksh
#
# @(#)$Id: realpathtest.sh,v 1.4 2008/04/14 19:36:54 jleffler Exp $
#
# Create confusing path names

base=${1:-"./rpt"}

mkdir -p $base/elsewhere/confused $base/elsewhere/hidden \
         $base/other/place $base/elsewhere/private

(
cd $base
[ -h link ] || ln -s elsewhere/confused link
[ -h some ] || ln -s other/place some
)
(
cd $base/elsewhere/confused
[ -h mischief ] || ln -s ../hidden mischief
[ -h where    ] || ln -s ../private where
)
(
cd $base/other/place
[ -h dubious  ] || ln -s ../../link/mischief dubious
[ -h doubtful ] || ln -s ../../link/where doubtful
)
(
cd $base/elsewhere/private
echo "What is the real pathname for $base/some/doubtful/file?" > file
)
(
cd $base/elsewhere/hidden
[ -h file ] || ln -s name file
echo "What is the real pathname for $base/some/dubious/file?" > name
)

for name in \
    $base/some/dubious/file \
    $base/some/doubtful/file \
    $base/elsewhere/confused/mischief/file \
    $base/elsewhere/confused/where/file
do
    if realpath $name
    then cat $(realpath -s $name)
    fi
done

Свяжитесь со мной, если вы хотите получить исходный текст программы 'realpath' или 'linkpath' (см. Мой профиль); , Программа 'realpath' не является ракетостроением - она в основном вызывает realpath() для каждого заданного аргумента. Там значительно больше усилий, связанных с анализом полного набора ссылок.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .