Sous Linux, l' readlink
utilitaire accepte une option -f
qui suit des liens supplémentaires. Cela ne semble pas fonctionner sur Mac et éventuellement sur des systèmes basés sur BSD. Quel serait l'équivalent?
Voici quelques informations de débogage:
$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]
readlink
peut s'agir d'une commande intégrée ou externe.touch myfile ; ln -s myfile otherfile ; perl -MCwd=abs_path -le 'print abs_path readlink(shift);' otherfile
... dans mon cas, je vois: / Users / cito / myfile`. Ajouté à ma réponse ci-dessous. À votre santé.Réponses:
readlink -f
fait deux choses:Si vous le souhaitez, vous pouvez simplement créer un script shell qui utilise le comportement vanlink readlink pour obtenir la même chose. Voici un exemple. De toute évidence, vous pouvez insérer ceci dans votre propre script où vous souhaitez appeler
readlink -f
Notez que cela n'inclut aucune gestion des erreurs. D'une importance particulière, il ne détecte pas les cycles de liens symboliques. Un moyen simple de le faire serait de compter le nombre de fois que vous parcourez la boucle et échouez si vous atteignez un nombre improbablement élevé, tel que 1 000.
MODIFIÉ à utiliser à la
pwd -P
place de$PWD
.Notez que ce script s'attend à être appelé comme
./script_name filename
, non-f
, changez$1
en$2
si vous voulez pouvoir l'utiliser avec-f filename
un lien de lecture GNU similaire.la source
foo -> /var/cux
, alorsfoo/bar
ne sera pas résolu, car cebar
n'est pas un lien, bien que cefoo
soit le cas.cd "$(dirname "$TARGET_FILE")"
etTARGET_FILE=$(readlink "$TARGET_FILE")
etTARGET_FILE=$(basename "$TARGET_FILE")
aux endroits appropriés dans le code ci-dessus.MacPorts et Homebrew fournissent un paquet coreutils contenant
greadlink
(GNU readlink). Nous remercions Michael Kallweitt de publier sur mackb.com.la source
.bashrc
:export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
pwd -P
etreadlink
sur OS X, sans rien installerPATH
. Est-ce que ce qui précède a commencé parbrew install <package> --default-names
. Plusieurs fois, une question sur ce site a reçu une réponse légèrement, ou plus, en dehors des exigences techniques du demandeur, mais dans la même situation, et a toujours été très utile. topbug.net/blog/2013/04/14/…Vous pourriez être intéressé par
realpath(3)
, ou Pythonos.path.realpath
. Les deux ne sont pas exactement les mêmes; l'appel à la bibliothèque C nécessite l'existence de composants de chemin intermédiaires, contrairement à la version Python.Je sais que vous avez dit que vous préféreriez quelque chose de plus léger qu'un autre langage de script, mais juste au cas où la compilation d'un binaire est insupportable, vous pouvez utiliser Python et ctypes (disponibles sur Mac OS X 10.5) pour encapsuler l'appel de bibliothèque:
Ironiquement, la version C de ce script devrait être plus courte. :)
la source
realpath
c'est bien ce que je veux. Mais il semble plutôt gênant que je doive compiler un binaire pour obtenir cette fonction à partir d'un script shell.readlink
, n'est-ce pas?)python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "${1}"
fonctionne avec des chemins comme'~/.symlink'
perl -MCwd=abs_path -le 'print abs_path readlink(shift);'
à ma réponse :-)Je déteste continuer avec une autre implémentation, mais j'avais besoin a) d' une implémentation portable, pure shell , et b) d' une couverture de test unitaire , car le nombre de cas de bord pour quelque chose comme ça n'est pas trivial .
Voir mon projet sur Github pour les tests et le code complet. Ce qui suit est un résumé de la mise en œuvre:
Comme Keith Smith le souligne astucieusement,
readlink -f
fait deux choses: 1) résout les liens symboliques récursivement, et 2) canonise le résultat, d'où:Tout d'abord, l'implémentation du résolveur symlink:
Notez qu'il s'agit d'une version légèrement simplifiée de l'implémentation complète . L'implémentation complète ajoute une petite vérification des cycles de liens symboliques , ainsi que masse la sortie un peu.
Enfin, la fonction de canonisation d'un chemin:
C'est plus ou moins ça. Assez simple à coller dans votre script, mais assez délicat pour que vous soyez fou de vous fier à n'importe quel code qui n'a pas de tests unitaires pour vos cas d'utilisation.
la source
local
mot - clé non-POSIXreadlink -f
, ni derealpath
. En supposant un Mac avec la formule coreutils installée (donc avecgreadlink
disponible), essayez ceci avecln -s /tmp/linkeddir ~/Documents
;greadlink -f /tmp/linkeddir/..
affiche votre répertoire personnel (il a résolu le/tmp/linkeddir
lien avant d'appliquer la..
référence du répertoire parent), mais votre code produit/private/tmp/
tel/tmp/linkeddir/..
quel n'est pas un lien symbolique, mais il-d /tmp/linkeddir/..
est vrai etcd /tmp/linkeddir/..
vous emmène donc vers/tmp
, dont le chemin canonique est/private/tmp
. Votre code fait ce qu'ilrealpath -L
fait à la place.Un simple liner en perl qui fonctionnera à coup sûr presque partout sans aucune dépendance externe:
Déréférencer les liens symboliques.
L'utilisation dans un script pourrait ressembler à ceci:
la source
-l
, commeperl -MCwd -le 'print Cwd::abs_path shift' ~/non-absolute/file
greadlink est le lien de lecture gnu qui implémente -f. Vous pouvez également utiliser macports ou autres, je préfère les homebrews.
la source
J'ai fait personnellement un script appelé realpath qui ressemble à un petit quelque chose comme:
la source
sys.argv[1]
si vous voulez que le script imprime le chemin réel du premier argument.sys.argv[0]
imprime simplement le chemin réel du script pyton lui-même, ce qui n'est pas très utile.~/.profile
:alias realpath="python -c 'import os, sys; print os.path.realpath(sys.argv[1])'"
readlink -f
, voici une version modifiée de l'alias de @jwhitlock pour supporter un-f
drapeau possible :alias realpath="python -c 'import os, sys; print os.path.realpath(sys.argv[2] if sys.argv[1] == \"-f\" else sys.argv[1])'"
Et ça?
la source
../../../
->/
/usr/bin/
par exemple comme lealternatives
système aime avoir.Voici une fonction shell portable qui devrait fonctionner dans n'importe quel shell Bourne comparable. Il résoudra la ponctuation relative du chemin ".. ou". et les liens symboliques de déréférencement.
Si, pour une raison quelconque, vous n'avez pas de commande realpath (1) ou readlink (1), cela peut être un alias.
Prendre plaisir:
De plus, juste au cas où quelqu'un serait intéressé, voici comment implémenter le nom de base et le nom de répertoire dans un code shell 100% pur:
Vous pouvez trouver la version mise à jour de ce code shell sur mon site Google: http://sites.google.com/site/jdisnard/realpath
EDIT: Ce code est autorisé sous les termes de la licence à 2 clauses (style freeBSD). Une copie de la licence peut être trouvée en suivant l'hyperlien ci-dessus vers mon site.
la source
FreeBSD et OSX ont une version
stat
dérivée de NetBSD.Vous pouvez ajuster la sortie avec des commutateurs de format (voir les pages de manuel sur les liens ci-dessus).
Certaines versions d'OS X
stat
peuvent ne pas avoir l'-f%R
option pour les formats. Dans ce cas, cela-stat -f%Y
peut suffire. L'-f%Y
option affichera la cible d'un lien symbolique, tandis que-f%R
le chemin d'accès absolu correspondant au fichier sera affiché.ÉDITER:
Si vous pouvez utiliser Perl (Darwin / OS X est installé avec des versions récentes de
perl
), alors:marchera.
la source
R
option à-f%
est manquante.stat -f%Y
Donne éventuellement la sortie souhaitée. Je vais ajuster la réponse. Notez que l'stat
outil est apparu dans FreeBSD dans la version 4.10 et NetBSD dans la version 1.6.Le moyen le plus simple de résoudre ce problème et d'activer la fonctionnalité de readlink sur Mac avec Homebrew installé ou FreeBSD est d'installer le package 'coreutils'. Peut également être nécessaire sur certaines distributions Linux et autres OS POSIX.
Par exemple, dans FreeBSD 11, j'ai installé en appelant:
# pkg install coreutils
Sur MacOS avec Homebrew, la commande serait:
$ brew install coreutils
Je ne sais pas vraiment pourquoi les autres réponses sont si compliquées, c'est tout. Les fichiers ne sont pas dans un endroit différent, ils ne sont tout simplement pas encore installés.
la source
brew install coreutils --with-default-names
Pour être plus précis. Ou vous vous retrouverez avec "greadlink" à la place ...pwd -P
est assez simple mais il disparaît parmi beaucoup d'autres réponses, y compris les réponses répétées, d'où le downvote.Commencer la mise à jour
C'est un problème si fréquent que nous avons créé une bibliothèque Bash 4 pour une utilisation gratuite (licence MIT) appelée realpath-lib . Ceci est conçu pour émuler readlink -f par défaut et comprend deux suites de tests pour vérifier (1) qu'il fonctionne pour un système Unix donné et (2) contre readlink -f s'il est installé (mais ce n'est pas obligatoire). De plus, il peut être utilisé pour rechercher, identifier et dérouler des liens symboliques profonds et rompus et des références circulaires, il peut donc être un outil utile pour diagnostiquer des problèmes de répertoires et de fichiers physiques ou symboliques profondément imbriqués. Il peut être trouvé sur github.com ou bitbucket.org .
Mettre à jour la fin
Une autre solution très compacte et efficace qui ne repose sur rien d'autre que Bash est:
Cela inclut également un paramètre d'environnement
no_symlinks
qui permet de résoudre les liens symboliques vers le système physique. Tant qu'ilno_symlinks
est défini sur quelque chose, c'est-à-dire que lesno_symlinks='on'
liens symboliques seront résolus vers le système physique. Sinon, ils seront appliqués (paramètre par défaut).Cela devrait fonctionner sur tout système qui fournit Bash et retournera un code de sortie compatible Bash à des fins de test.
la source
Il y a déjà beaucoup de réponses, mais aucune n'a fonctionné pour moi ... C'est donc ce que j'utilise maintenant.
la source
$target
est un chemin d'accès, cela ne fonctionne que si c'est un fichier.Une manière paresseuse qui fonctionne pour moi,
la source
Mieux vaut tard que jamais, je suppose. J'étais motivé à développer cela spécifiquement parce que mes scripts Fedora ne fonctionnaient pas sur Mac. Le problème, ce sont les dépendances et Bash. Les Mac n'en ont pas, ou s'ils le font, ils sont souvent ailleurs (autre chemin). La manipulation du chemin de dépendance dans un script Bash multiplateforme est au mieux un casse-tête et au pire un risque pour la sécurité - il est donc préférable d'éviter leur utilisation, si possible.
La fonction get_realpath () ci-dessous est simple, centrée sur Bash et aucune dépendance n'est requise. J'utilise uniquement l' écho et le cd de Bash builtins . Il est également assez sécurisé, car tout est testé à chaque étape du processus et renvoie des conditions d'erreur.
Si vous ne voulez pas suivre les liens symboliques, placez set -P à l'avant du script, mais sinon cd devrait résoudre les liens symboliques par défaut. Il a été testé avec des arguments de fichier qui sont {absolus | parent | lien symbolique | local} et il renvoie le chemin absolu du fichier. Jusqu'à présent, nous n'avons eu aucun problème avec cela.
Vous pouvez combiner cela avec d'autres fonctions get_dirname, get_filename, get_stemname et validate_path. Ceux-ci peuvent être trouvés dans notre référentiel GitHub sous realpath-lib (divulgation complète - c'est notre produit mais nous le proposons gratuitement à la communauté sans aucune restriction). Il pourrait également servir d'outil pédagogique - il est bien documenté.
Nous avons fait de notre mieux pour appliquer les pratiques dites de «Bash moderne», mais Bash est un gros sujet et je suis certain qu'il y aura toujours place à amélioration. Il nécessite Bash 4+ mais pourrait fonctionner avec des versions plus anciennes si elles existent toujours.
la source
Étant donné que mon travail est utilisé par des personnes non Linux BSD ainsi que macOS, j'ai opté pour l'utilisation de ces alias dans nos scripts de construction (
sed
inclus car il a des problèmes similaires):Vérification facultative que vous pourriez ajouter pour installer automatiquement les dépendances homebrew + coreutils :
Je suppose que pour être vraiment "global", il faut en vérifier d'autres ... mais cela se rapproche probablement de la marque 80/20.
la source
Explication
coreutils est un
brew
paquet qui installe les utilitaires principaux GNU / Linux qui correspondent à leur implémentation Mac OSX afin que vous puissiez les utiliserVous pouvez trouver des programmes ou des utilitaires sur votre système mac osx qui semblent similaires aux coreutils Linux ("Core Utilities") mais ils diffèrent à certains égards (comme avoir des drapeaux différents).
En effet, l'implémentation Mac OSX de ces outils est différente. Pour obtenir le comportement original de type GNU / Linux, vous pouvez installer le
coreutils
package via lebrew
système de gestion des packages.Cela installera les utilitaires de base correspondants, préfixés par
g
. Par exemple pourreadlink
, vous trouverez ungreadlink
programme correspondant .Afin de faire
readlink
fonctionner comme l' implémentation GNUreadlink
(greadlink
), vous pouvez créer un alias simple après avoir installé coreutils.la mise en oeuvre
Suivez les instructions sur https://brew.sh/
brew install coreutils
Vous pouvez placer votre alias dans ~ / .bashrc, ~ / .bash_profile, ou partout où vous avez l'habitude de conserver vos alias bash. Personnellement, je garde le mien dans ~ / .bashrc
alias readlink=greadlink
Vous pouvez créer des alias similaires pour d'autres coreutils tels que gmv, gdu, gdf, etc. Mais sachez que le comportement GNU sur une machine mac peut être déroutant pour les autres habitués à travailler avec des coreutils natifs, ou peut se comporter de manière inattendue sur votre système mac.
la source
J'ai écrit un utilitaire realpath pour OS X qui peut fournir les mêmes résultats que
readlink -f
.Voici un exemple:
Si vous utilisez MacPorts, vous pouvez l' installer avec la commande suivante:
sudo port selfupdate && sudo port install realpath
.la source
Vraiment indépendant de la plate-forme serait également ce R-onliner
Pour imiter réellement
readlink -f <path>
, 2 $ au lieu de 1 $ devraient être utilisés.la source
Implémentation conforme POSIX
readlink -f
pour les scripts shell POSIXhttps://github.com/ko1nksm/readlinkf
Ceci est compatible POSIX (pas de bashisme). Il n'utilise ni
readlink
nirealpath
. J'ai vérifié que c'est exactement la même chose en comparant avec GNUreadlink -f
(voir les résultats des tests ). Il a une gestion des erreurs et de bonnes performances. Vous pouvez remplacer en toute sécurité à partir dereadlink -f
. La licence est CC0, vous pouvez donc l'utiliser pour n'importe quel projet.Veuillez vous référer au dernier code. Il peut en être corrigé.
la source
Perl a une fonction readlink (par exemple, comment copier des liens symboliques dans Perl? ). Cela fonctionne sur la plupart des plates-formes, y compris OS X:
Par exemple:
la source
readlink
sans l'-f
option - pas de récursivité, pas de chemin absolu -, vous pouvez donc aussi utiliserreadlink
directement.La réponse de @Keith Smith donne une boucle infinie.
Voici ma réponse, que j'utilise uniquement sur SunOS (SunOS manque tellement de commandes POSIX et GNU).
C'est un fichier script que vous devez mettre dans l'un de vos répertoires $ PATH:
la source
Voici ce que j'utilise:
stat -f %N $your_path
la source
Les chemins d'accès à readlink sont différents entre mon système et le vôtre. Veuillez essayer de spécifier le chemin complet:
la source
readlink
compatible avec GNU. C'est agréable à savoir, mais cela ne résout pas mon problème, car j'ai besoin que mon script s'exécute sur la machine d'autres personnes, et je ne peux pas leur demander d'installer fink pour cela.