Comment obtenir le chemin complet du fichier original d'un lien symbolique symbolique?

99

Je veux scpun fichier sur un serveur. Le fichier est un lien symbolique et ce que je veux réellement faire, c'est copier le fichier source. Quoi qu'il en soit, je ne veux pas suivre le chemin du fichier source manuellement, car il peut être remplacé. Si je peux obtenir le chemin absolu du fichier source, je le pourrai sep. Comment puis-je obtenir le chemin?

Eonil
la source
2
La plupart des scpversions suivent des liens symboliques par défaut, n'est-ce pas? Vous devriez vérifier le vôtre et peut-être vous épargner du travail.
Jw013
@ jw103 Merci de me l'avoir fait savoir. Je ne savais pas. :)
Eonil
2
Note: scp -roblige à suivre les liens symboliques.
Eonil

Réponses:

129

Essayez cette ligne:

readlink -f `which command`

Si commandest dans votre $PATHvariable, sinon vous devez spécifier le chemin que vous connaissez.

Marguerite
la source
12
-fretournera un chemin vers une cible finale inexistante, tant que les cibles de liens intermédiaires existent ... Utilisez -epour éviter cela, c'est-à-dire. -eretournera null si la cible finale n'existe pas.
Peter.O
10
-ferrored avec readlink: illegal option -- fdans OSX. Le retirer a bien fonctionné.
Frontières Heath
2
@HeathBorders Pour OSX, si vous avez installé homebrew coreutils, vous pouvez également l'utiliser à la greadlinkplace.
Adam Gent
23

Sous Linux, readlinklit le contenu d'un lien symbolique et readlink -fsuit les liens symboliques vers les liens symboliques vers les liens symboliques, etc., jusqu'à ce qu'il trouve quelque chose qui n'est pas un lien symbolique.

Cela n’est cependant pas nécessaire pour scp: scp suit toujours les liens symboliques (il copie toujours le contenu du fichier, en ignorant les métadonnées sauf que -ples durées et les modes du fichier sont préservés lorsque cela est possible).

Si vous êtes déçu par ce que les métadonnées scp peuvent et ne peuvent pas préserver, je suggère d'utiliser rsync. Sans option, rsync copie le contenu du fichier en ignorant les métadonnées. L'option couramment utilisée -apréserve toutes les métadonnées de variétés de jardins (heures, liens symboliques, autorisations et droits de propriété), et il existe des options permettant de préserver les métadonnées exotiques telles que les ACL et les liens physiques.

Gilles
la source
readlink ne fait qu'une seule étape pour la liaison de lecture. Par exemple, dans Ubuntu, nous avons / bin / zsh, qui est lié symboliquement à / etc / alternatives / zsh, mais il s'agit du deuxième lien symbolique. Enfin, nous n'obtiendrons pas de chemin de fichier ou de répertoire réel. La même chose est avec la commande stat. Seul readlink avec l'option -f résout toutes les tâches.
Znik
9

J'utilise la commande ls, stat, readlink.

Prenez le fichier /etc/localtimecomme exemple

[flying@lempstacker ~]$ ls /etc/localtime 
/etc/localtime
[flying@lempstacker ~]$ ls -l /etc/localtime
lrwxrwxrwx. 1 root root 35 Aug  2 22:41 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai

Opération

En utilisant stat

[flying@lempstacker ~]$ stat /etc/localtime
  File: ‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’
  Size: 35          Blocks: 0          IO Block: 4096   symbolic link
Device: fd01h/64769d    Inode: 272202388   Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-11-23 09:00:59.999887800 +0800
Modify: 2016-08-02 22:41:26.090389904 +0800
Change: 2016-08-02 22:41:26.090389904 +0800
 Birth: -
[flying@lempstacker ~]$ stat -c "%N" /etc/localtime
‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’

Utiliser readlink

[flying@lempstacker ~]$ readlink /etc/localtime
../usr/share/zoneinfo/Asia/Shanghai
[flying@lempstacker ~]$ readlink -f /etc/localtime
/usr/share/zoneinfo/Asia/Shanghai

Il semble que cette commande readlink -fest meilleure.

Explication

-f, --canonicalize: canonise en suivant chaque lien symbolique dans chaque composant du nom donné de manière récursive; tout sauf le dernier composant doit exister —— Deman readlink

Gorgone
la source
6

Stat vous donnera ces informations:

$ stat current
  File: `current' -> `/home/user/releases/build/'
  ...
polynôme
la source
readlink ne fait qu'une seule étape pour la liaison de lecture. Par exemple, dans Ubuntu, nous avons / bin / zsh, qui est lié symboliquement à / etc / alternatives / zsh, mais il s'agit du deuxième lien symbolique. Enfin, nous n'obtiendrons pas de chemin de fichier ou de répertoire réel. La même chose est avec la commande stat. Seul readlink avec l'option -f résout toutes les tâches.
Znik
5

Vous pouvez soit faire

readlink -f `which command`

ou vous pouvez obtenir quelque chose de similaire dans Linux avec

stat `which command` | grep File

Si vous ajoutez ceci à un script, inspectez l'erreur. Si vous ne voulez pas voir le message d'erreur dans le cas où le lien sym n'est pas là, allez avec quelque chose comme

readlink -f "`which command`" 
Alexandre Santos
la source
stat et realink sans -f ne font qu'un seul pas. Mieux vaut alors appeler readlink -f.
Znik
3

Je voudrais utiliser realpath <symlink>.

Probablement ce que vous appelez 'source' est le fichier 'cible' en fonction de l'utilisation de ln:Usage: ln [OPTION]... [-T] TARGET LINK_NAME

XavierStuvw
la source
Merci Cela a fonctionné comme un charme! avec Mac OSX! où readlinkne l'a pas coupé ... stupide mac. lol
JayRizzo
0

readlink -f 'which java' n'a pas fonctionné pour moi.

Mais cela a:

readlink -f $(which java)
NonCreature0714
la source
3
N'a pas fonctionné parce que ce n'est `pas '.. mais $()c'est de toute façon une meilleure pratique.
Stephen Rauch
Pourquoi downvote? Ma réponse est une alternative acceptable et, comme le dit le commentaire, une meilleure pratique.
NonCreature0714
1
La plupart des gens qui votent à la baisse ne commentent pas également, donc demander une explication sur un vote à la baisse vous obtiendra rarement une explication, parce que l'électeur à la baisse est déjà parti et ne risque pas de revenir. Je vous suggère de supprimer le code tapé qui ne fonctionne pas dans votre réponse. Je serais prêt à voter si vous preniez le temps de le nettoyer et d'expliquer pourquoi $()est une meilleure pratique.
Stephen Rauch
Comme Stephen vous l'a expliqué, "n'est pas". Vous devriez encapsuler par command, mais c'est obsolète. L'utilisation de $ () est préférable, car l'encapsulation $ ($ (commande)) est beaucoup plus facile et ne nécessite pas d'échappement spécial. Alors c'est préféré. Dans votre premier exemple, vous utilisiez l'apostrophe habituelle, puis readlink essayait de trouver le fichier nommé 'which java' avec un espace dans son nom. Mais vous avez l’intention d’appeler la commande qui, avec l’argument java, vous permet de trouver le chemin d’exécutable binaire java.
Znik
0

Sur MAC OX, le paramètre "-f" ne fonctionne pas, "readlink" fonctionne sans paramètre.

KZs-MacBook-Pro:bin kz$ readlink -f pip3
readlink: illegal option -- f
usage: readlink [-n] [file ...]

KZs-MacBook-Pro:bin kz$ readlink pip3
../../../Library/Frameworks/Python.framework/Versions/3.7/bin/pip3
Xb74Dkjb
la source