In diesem Beispiel:
mkdir a
ln -s a b
ln -s b c
ln -s c d
Wenn ich ausführe:
ls -l d
Wird sich zeigen:
d -> c
Gibt es eine Möglichkeit ls
, d -> c -> b -> a
stattdessen einen anderen Linux-Befehl anzuzeigen ?
In diesem Beispiel:
mkdir a
ln -s a b
ln -s b c
ln -s c d
Wenn ich ausführe:
ls -l d
Wird sich zeigen:
d -> c
Gibt es eine Möglichkeit ls
, d -> c -> b -> a
stattdessen einen anderen Linux-Befehl anzuzeigen ?
Antworten:
Verwenden Sie einfach namei
:
$ namei d
f: d
l d -> c
l c -> b
l b -> a
d a
ls
. Vielen Dank!
readlink -e <link>
readlink [OPTION] ... DATEI
- -e, --canonicalize-existing
canonicalize, indem rekursiv jedem Symlink in jeder Komponente des angegebenen Namens gefolgt wird, müssen alle Komponenten existieren
$ 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
Hinweis: readlink a selbst gibt b zurück
note # 2: zusammen mit find -l kann ein Dienstprogramm zum Auflisten der Ketten leicht in Perl geschrieben werden, muss aber auch intelligent genug sein, um Schleifen zu erkennen
readlink gibt nichts aus, wenn Sie eine Schleife haben. Das ist wohl besser als stecken zu bleiben.
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
undgreadlink -e <link>
Hier ist eine rekursive Funktion in 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; }
In mehreren Zeilen:
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
}
Beispiele:
$ chain d
d -> c -> b -> a
$ chain c
c -> b -> a
$ chain a
a
Es erfordert, stat(1)
die auf einigen Systemen möglicherweise nicht vorhanden sind.
Es schlägt fehl, wenn Namen Backticks, einfache Anführungszeichen oder "->" enthalten. Es bleibt in einer Schleife mit Symlink-Schleifen stecken (dies könnte mit einem assoziativen Array in Bash 4 gelöst werden). Es exportiert eine Variable namens "chain", unabhängig davon, ob sie bereits verwendet wird.
Es kann andere Probleme damit geben.
Bearbeiten:
Ein Problem mit einigen relativen Symlinks wurde behoben. Einige funktionieren immer noch nicht, aber für die folgende Version muss das Ziel des Links nicht vorhanden sein.
Es wurde eine Version hinzugefügt, die readlink verwendet:
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
scheint das nicht zu zeigen. Java auf Ubuntu ist:/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java