Finde nur das Ziel von symlink

50

Für die Verwendung in einem Shell-Skript suche ich nach einer Befehlszeile, um das Ziel eines symbolischen Links zu ermitteln. Das nächste was ich bisher gesehen habe ist stat -N src, welche Ausgänge src -> dst. Natürlich könnte ich die Ausgabe analysieren und abrufen dst, aber ich frage mich, ob es eine direkte Möglichkeit gibt, das Ziel zu ermitteln.

Gerrit
quelle

Antworten:

61

Eine weitere Option wäre die Verwendung des speziell entwickelten Befehls, readlinkfalls verfügbar.

Z.B

$ readlink -f `command -v php`
/usr/bin/php7.1
nikitautiu
quelle
21
Verwenden readlink -fSie diese Option, wenn Sie das letzte Symlink-Ziel und nicht nur das nächste kennen möchten .
scai
Guter Punkt! Vergessen dass.
Nikitautiu
11
Beachten Sie, dass dies -feine nicht portable Erweiterung von GNU ist readlink.
Bahamat
2
Wann wäre der Readlink nicht verfügbar? Vielen Dank.
tommy.carstensen
2
@ tommy.carstensen readlink (1) wurde 2003 zu GNU coreutils hinzugefügt, so dass Sie sich heutzutage wahrscheinlich auf praktisch alle Systeme verlassen können, die coreutils verwenden. (Vgl. Git.savannah.gnu.org/cgit/coreutils.git/commit/src/… )
Josip Rodin
16

Unter Mac OS X und FreeBSD / NetBSD / etc. es ist:

stat -f %Y <filename>

Allgemeiner denke ich, dass die Lösung ist (stat --printf =% N verwendet seltsame Anführungszeichen):

ls -l b | sed -e 's/.* -> //'

Beispiel:

# ln -s a b
# stat -f %Y b
a

Eine andere Methode ist:

# find b -maxdepth 0 -printf %l
a#

Die letzte Zeile ist verstümmelt, weil es keine neue Zeile gibt, aber das ist in Ordnung, wenn Sie das Ergebnis in einer Variablen wie dieser benötigen

# f=$(find b -maxdepth 0 -printf %l)
# echo $f
a

Das -maxdepthwird benötigt, um zu verhindern, dass es findin Verzeichnisse babfällt, wenn es sich zufällig um ein Verzeichnis handelt.

Coroos
quelle
Ich entrahmte völlig über stat --printf='%N\n'ist genau das, was ich will, seltsame Zitate nicht stören mich, ihr die gleichen Zitate rm und ln --interactive Verwendung
ThorSummoner
Dies ist anscheinend nicht portierbar, da unter Linux der stat (1) der GNU-Coreutils andere Parameter hat und link -> destin der Ausgabe ausgedruckt wird. Die find (1) -Lösung sollte überprüft werden, ob es mit GNU-Findutils oder auf andere Weise ...
Josip Rodin
Vergessen Sie bitte nicht, Ihre variablen Erweiterungen echo $f/*
anzugeben
3

Dies kann GNU erfolgen mit find: find src -prune -printf "%l\n".

Gerrit
quelle
1

Portabel: kein Glück außer der Verwendung von Heuristiken, um ls -l-Ausgaben zu analysieren oder zu verwenden perl -le 'print readlink("some-file")'

Einige Systeme verfügen über einen readlinkBefehl, andere über eine -fOption zum Abrufen des absoluten Pfads.

Es gibt verschiedene Implementierungen eines statBefehls als Wrapper für die stat/ lstatsystem-Aufrufe. Die GNU-Version ist in dieser Hinsicht nicht nützlich, aber die integrierte Version von zsh ist eher so:

zmodload zsh/stat
stat +link the-link

Noch mit zsh können Sie den absoluten Pfad einer Datei (entfernt jede Symlink-Komponente) mit dem :AModifikator abrufen (gilt für Variablenerweiterung, Verlaufserweiterung und Globbing:

~$ gstat -c %N b
`b' -> `a'
~$ var=b
~$ echo $var:A
/home/me/a
~$ echo b(:A)
/home/me/a
~$ echo ?(@:A)
/home/me/a
Stéphane Chazelas
quelle
1

Auf einem System, auf dem ich keine readlinkoder statBefehle habe, aber Python 2.x, verwende ich ein kurzes Skript:

#!/usr/bin/env python

import os, sys

if __name__ == "__main__":
    src = sys.argv[1]
    target = os.readlink(src)
    if not os.path.isabs(target):
            target = os.path.abspath(os.path.join(os.path.dirname(src), target))
    print target

Beachten Sie, dass im Gegensatz readlink -fdazu nur eine Ebene von Symlink folgen darf.

Rakslice
quelle
1

Tragbarer reiner Bash Realpath

bash_realpath() {
  # print the resolved path
  # @params
  # 1: the path to resolve
  # @return
  # &1: the resolved link path

  local path="${1}"
  while [[ -L ${path} && "$(ls -l "${path}")" =~ -\>\ (.*) ]]
  do
    path="${BASH_REMATCH[1]}"
  done
  echo "${path}"
}
Léa Gris
quelle
0

realpathBefehl des coreutilsPakets,

wie in readlinkder Handbuchseite des Befehls verlinkt .


zum Beispiel:

realpath /bin/python

Ausgänge

/usr/bin/python2.7

auf meiner Maschine.


quelle