Rechercher uniquement la destination du lien symbolique

50

Pour une utilisation dans un script shell, je cherche un moyen en ligne de commande pour obtenir la destination d'un lien symbolique. Le plus proche que je suis venu jusqu'ici est stat -N src, qui produit src -> dst. Bien sûr, je pourrais analyser le résultat et obtenir dst, mais je me demande s’il existe un moyen direct d’obtenir la destination.

gerrit
la source

Réponses:

61

Une autre option consisterait à utiliser la commande spécialement conçue, le readlinkcas échéant.

Par exemple

$ readlink -f `command -v php`
/usr/bin/php7.1
Nikitautiu
la source
21
Utilisez-le readlink -fsi vous voulez connaître la dernière cible de lien symbolique et pas seulement la suivante .
scai
Bon point! Oublie ça.
Nikitautiu
11
Notez que -fc'est une extension non-portable à GNU readlink.
Bahamat
2
Quand est-ce que readlink ne serait pas disponible? Merci.
tommy.carstensen
2
@ tommy.carstensen readlink (1) a été ajouté à GNU coreutils en 2003, vous pouvez donc en dépendre aujourd'hui sur pratiquement tous les systèmes utilisant coreutils. (Cf. git.savannah.gnu.org/cgit/coreutils.git/commit/src/… )
Josip Rodin
16

Sur Mac OS X et FreeBSD / NetBSD / etc. ses:

stat -f %Y <filename>

Plus généralement, je suppose que la solution est la suivante (stat --printf =% N utilise des guillemets étranges):

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

Exemple:

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

Une autre méthode est:

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

La dernière ligne est mutilée car elle n’a pas de nouvelle ligne, mais c’est bien si vous avez besoin du résultat dans une variable, comme ceci

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

Le -maxdepthest nécessaire pour empêcher la finddescente dans les répertoires s’il bs’agit d’un répertoire.

Coroos
la source
J'ai totalement écrémé, stat --printf='%N\n'c'est exactement ce que je veux, les citations étranges ne me dérangent pas, leurs mêmes citations rm et ln - utilisation interactive
ThorSummoner
Ce n'est apparemment pas portable, car sous Linux, stat (1) de GNU coreutils a différents paramètres et est imprimé link -> destdans la sortie. La solution find (1) doit être vérifiée si c'est avec GNU findutils ou autrement ...
Josip Rodin
N'oubliez pas de citer vos développements variables, echo $fmais cela ne produira certainement pas ce que vous attendez lorsque le lien symbolique pointe vers /*(oui, c'est possible)
Camusensei
3

Cela peut être fait en utilisant GNU find: find src -prune -printf "%l\n".

gerrit
la source
1

Portable: pas de chance si ce n'est d'utiliser des heuristiques pour analyser la sortie ls -l ou utiliser perl -le 'print readlink("some-file")'

Certains systèmes ont une readlinkcommande, certains avec une -foption pour obtenir le chemin absolu.

Il existe différentes implémentations d'une statcommande en tant que wrapper pour les appels stat/ lstatsystem. GNU one n’est pas utile à cet égard, mais celui qui est intégré à zsh l’est plus:

zmodload zsh/stat
stat +link the-link

Toujours avec zsh, vous pouvez obtenir le chemin absolu d’un fichier (supprime chaque composant de lien symbolique) avec le :Amodificateur (s’applique au développement de variable, au développement d’historique et au déplacement:

~$ 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
la source
1

Sur un système où je n'ai readlinkni statcommandes, mais Python 2.x, j'utilise un court script:

#!/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

Notez que contrairement à readlink -fcela, il ne peut suivre qu'un seul niveau de lien symbolique.

rakslice
la source
1

Realpath portable pur Bash

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
la source
0

realpathcommande de coreutilspackage,

comme lié dans readlinkla page de manuel de la commande.


par exemple:

realpath /bin/python

les sorties

/usr/bin/python2.7

sur ma machine.


la source