web-dev-qa-db-fra.com

Découvrez la cible du lien symbolique via la ligne de commande

Supposons que j'établisse un lien symbolique:

ln -s /root/Public/mytextfile.txt /root/Public/myothertextfile.txt

existe-t-il un moyen de voir quel est l'objectif de myothertextfile.txt utilise la ligne de commande?

141
Jared

Utilisez le -f flag pour imprimer la version canonisée. Par exemple:

readlink -f /root/Public/myothertextfile.txt

De man readlink:

-f, --canonicalize
      canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
184
brian-brazil

readlink est la commande que vous souhaitez. Vous devriez regarder la page de manuel de la commande. Parce que si vous voulez suivre une chaîne de liens symboliques vers le fichier réel, vous avez besoin du commutateur -e ou -f:

$ ln -s foooooo zipzip   # fooooo doesn't actually exist
$ ln -s zipzip zapzap

$ # Follows it, but doesn't let you know the file doesn't actually exist
$ readlink -f zapzap
/home/kbrandt/scrap/foooooo

$ # Follows it, but file not there
$ readlink -e zapzap

$ # Follows it, but just to the next symlink
$ readlink zapzap
zipzip
25
Kyle Brandt

Cela fonctionnera également:

ls -l /root/Public/myothertextfile.txt

mais readlink serait préférable pour une utilisation dans un script plutôt que d'analyser ls.

Si vous souhaitez afficher la source et la destination du lien, essayez stat -c%N files*. Par exemple.

$ stat -c%N /dev/fd/*
‘/dev/fd/0’ -> ‘/dev/pts/4’
‘/dev/fd/1’ -> ‘/dev/pts/4’

Ce n'est pas bon pour l'analyse (utilisez readlink pour cela), mais il montre le nom du lien et la destination, sans l'encombrement de ls -l

-c peut être écrit --format et %N signifie "nom de fichier cité avec déréférence si lien symbolique".

5
Robert Siemer

Le readlink est une bonne chose, mais spécifique à GNU et non multiplateforme. J'avais l'habitude d'écrire des scripts multiplateformes pour /bin/sh, donc j'utiliserais quelque chose comme:

 ls -l /root/Public/myothertextfile.txt | awk '{print $NF}'

ou:

 ls -l /root/Public/myothertextfile.txt | awk -F"-> " '{print $2}'

mais ceux-ci doivent être testés sur différentes plates-formes. Je pense qu'ils fonctionneront, mais je ne suis pas sûr à 100% du format de sortie ls.

Le résultat de ls peut également être analysé dans bash sans dépendre d'une commande externe comme awk, sed ou Perl.

Cette bash_realpath fonction, résout la destination finale d'un lien (lien → lien → lien → final):

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}"
}

La question n'est pas assez précise pour donner une réponse simple comme celle de brian-brazil:

readlink -f some_path

va en effet déréférencer chaque lien symbolique impliqué dans la construction du chemin vers cible finale derrière some_path.

Mais un niveau de liens symboliques en cascade n'est qu'un cas particulier parmi d'autres dans un système, le cas général étant N niveaux de liens symboliques en cascade. Regardez les éléments suivants sur mon système:

$ rwhich emacs
/usr/bin/emacs
 /etc/alternatives/emacs
  /usr/bin/emacs24-x

rwhich est ma propre implémentation récursive de which qui affiche tous les liens symboliques intermédiaires en cascade (vers stderr) jusqu'à la cible finale (vers stdout).

Alors si je veux savoir ce que c'est:

  • la cible du lien symbolique/usr/bin/emacs **, la réponse évidente pour moi est /etc/alternatives/emacs tel que retourné par:

    readlink $(which emacs)
    readlink /usr/bin/emacs
    
  • la cible finale derrière les liens symboliques en cascade/usr/bin/emacs, la réponse sera /usr/bin/emacs24-x tel que retourné par:

    readlink -f $(which emacs)
    readlink -f /usr/bin/emacs
    rwhich emacs 2>/dev/null
    
1
Nico

Si vous ne pouvez pas utiliser readlink, alors analyser le résultat de ls -l pourrait se faire comme ça.

Le résultat normal serait:

ls -l /root/Public/myothertextfile.txt
lrwxrwxrwx 1 root root 30 Jan  1 12:00 /root/Public/myothertextfile.txt -> /root/Public/mytextfile.txt

Nous voulons donc tout remplacer avant "->" et la flèche incluse. Nous pourrions utiliser sed pour cela:

ls -l /root/Public/myothertextfile.txt | sed 's/^.* -> //'
/root/Public/mytextfile.txt
1
7ochem

ll ou ls -l devrait répertorier les éléments du répertoire, y compris votre lien symbolique et sa cible

cd -P /root/Public/myothertextfile.txt (dans votre cas) doit pointer vers le chemin d'origine

0
Mantz

Si vous trouvez la cible de tous les liens dans un dossier et son sous-dossier, utilisez le find . -type l -ls commande avec le type de lien comme suit:

[email protected]:~/test$ find . -type l -ls
8601855888        0 lrwxr-xr-x    1 me           staff                   6 Jan 24 19:53 ./link -> target

Si vous voulez la cible d'un seul, alors ls -l devrait marcher:

[email protected]:~/test$ ls -l 
total 0
lrwxr-xr-x  1 me  staff  6 Jan 24 19:53 link -> target
-rw-r--r--  1 me  staff  0 Jan 24 19:53 target
0
Memin