З огляду на цей приклад:
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
?
З огляду на цей приклад:
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
?
Відповіді:
Просто використовуйте namei
:
$ namei d
f: d
l d -> c
l c -> b
l b -> a
d a
ls
. Спасибі!
readlink -e <link>
readlink [ОПЦІЯ] ... ФАЙЛ
- -e, --канонізувати існуючу
канонізацію, дотримуючись кожне символьне посилання в кожному компоненті даної назви рекурсивно, всі компоненти повинні існувати
$ 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)
brew install coreutils
іgreadlink -e <link>
Ось рекурсивна функція в 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
}
readlink
, схоже , цього не показують. Java на Ubuntu є:/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java