J'essaie d'obtenir le chemin absolu vers le script en cours d'exécution sur OS X.
J'ai vu de nombreuses réponses readlink -f $0
. Cependant, puisque OS X readlink
est le même que BSD, cela ne fonctionne tout simplement pas (cela fonctionne avec la version de GNU).
Y a-t-il une solution prête à l'emploi à cela?
$( cd "$(dirname "$0")" ; pwd -P )
Réponses:
Il y a une
realpath()
fonction C qui fera le travail, mais je ne vois rien de disponible sur la ligne de commande. Voici un remplacement rapide et sale:Cela imprime le chemin textuellement s'il commence par un
/
. Sinon, il doit s'agir d'un chemin relatif, il est donc précédé$PWD
du début . La#./
pièce se détache./
de l'avant$1
.la source
realpath ../something
renvoie$PWD/../something
command -v realpath >/dev/null 2>&1 || realpath() { ... }
Ces trois étapes simples vont résoudre ce problème et de nombreux autres problèmes OS X:
brew install coreutils
grealpath .
(3) peut être changé en juste
realpath
, voir (2) sortiela source
$( cd "$(dirname "$0")" ; pwd -P )
fonctionnent bien pour moi.XXX
et quelqu'uncd xxx
puispwd
retournera.../xxx
. À l'exception de cette réponse, toutes les solutions ci-dessus reviennentxxx
lorsque ce que vous voulez vraiment estXXX
. Je vous remercie!realpath
, que se passe-t-il lorsque vous aurez presque certainement besoin d'autres articlescoreutils
? Réécrire ces fonctions dans bash aussi? : PPouah. J'ai trouvé les réponses précédentes un peu insuffisantes pour plusieurs raisons: en particulier, elles ne résolvent pas plusieurs niveaux de liens symboliques, et elles sont extrêmement "Bash-y". Alors que la question originale demande explicitement un "script Bash", elle fait également mention du BSD de Mac OS X, non GNU
readlink
. Voici donc une tentative de portabilité raisonnable (je l'ai vérifié avec bash comme «sh» et dash), résolvant un nombre arbitraire de liens symboliques; et il devrait également fonctionner avec des espaces dans le (s) chemin (s), même si je ne suis pas sûr du comportement s'il y a un espace blanc le nom de base de l'utilitaire lui-même, alors peut-être, euh, éviter cela?J'espère que cela peut être utile à quelqu'un.
la source
local
pour les variables définies dans la fonction pour ne pas polluer l'espace de noms global. Par exemplelocal OURPWD=...
. Fonctionne au moins pour bash.BASENAME=$(basename "$LINK")
à l'intérieur du while et de l'utiliser dans le deuxième setter LINK et le setter..
les références parent comme lerealpath
ferait. Avec homebrewcoreutils
installé, essayezln -s /var/log /tmp/linkexample
alorsrealpath /tmp/linkexample/../
; cela imprime/private/var
. Mais votre fonction produit à la/tmp/linkexample/..
place, car ce..
n'est pas un lien symbolique.Une variante plus conviviale de la solution Python en ligne de commande:
la source
python -c "import os; import sys; print(os.path.realpath(sys.argv[1]))"
Je cherchais une solution à utiliser dans un script de provision de système, c'est-à-dire à exécuter avant même que Homebrew ne soit installé. En l'absence de solution appropriée, je déchargerais simplement la tâche vers un langage multiplateforme, par exemple Perl:
Le plus souvent, ce que nous voulons réellement, c'est le répertoire contenant:
la source
FULLPATH=$(perl -e "use Cwd 'abs_path'; print abs_path('$0')")
. Une raison contre?''
n'est pas à l'épreuve des balles. Il casse s'il$0
contient un guillemet simple, par exemple. Un exemple très simple: essayez votre version dans/tmp/'/test.sh
, et appelez/tmp/'/test.sh
par son chemin complet./tmp/'.sh
.Puisqu'il existe un chemin réel comme d'autres l'ont souligné:
Makefile:
Ensuite, compilez avec
make
et mettez un lien souple avec:ln -s $(pwd)/realpath /usr/local/bin/realpath
la source
gcc realpath.c -o /usr/local/bin/realpath
?/usr/local/bin
Utilisez Python pour l'obtenir:
la source
dirname
donnera le nom du répertoire de/path/to/file
, ie/path/to
.cd /path/to; pwd
garantit que le chemin est absolu.basename
donnera juste le nom de fichier dans/path/to/file
, iefile
.la source
Donc, comme vous pouvez le voir ci-dessus, j'ai pris une photo il y a environ 6 mois. Je l'ai totalement oublié jusqu'à ce que je me retrouve à nouveau dans le besoin d'une chose similaire. J'ai été complètement choqué de voir à quel point c'était rudimentaire; Je m'apprends à coder de manière assez intensive depuis environ un an maintenant, mais j'ai souvent l'impression que je n'ai peut-être rien appris du tout quand les choses vont au pire.
Je supprimerais la «solution» ci-dessus, mais j'aime vraiment qu'elle soit en quelque sorte un enregistrement de tout ce que j'ai vraiment appris au cours des derniers mois.
Mais je m'éloigne du sujet. Je me suis assis et j'ai tout travaillé hier soir. L'explication dans les commentaires devrait être suffisante. Si vous souhaitez suivre la copie sur laquelle je continue de travailler, vous pouvez suivre l'essentiel. Cela fait probablement ce dont vous avez besoin.
la source
..
les références parentes; par exemple,/foo/link_to_other_directory/..
est résolu comme/foo
plutôt que comme parent du chemin vers lequel/foo/link_to_other_directory
pointe le lien symbolique .readlink -f
etrealpath
résoudre chaque composant de chemin en commençant à la racine et en mettant à jour les cibles de lien en tête vers le reste en cours de traitement. J'ai ajouté une réponse à cette question pour réimplémenter cette logique.realpath pour Mac OS X
Exemple avec chemin associé:
Exemple avec dossier personnel
la source
..
elle ne produit pas la bonne réponse, j'ai donc ajouté un contrôle si le chemin donné est un répertoire:if test -d $path ; then echo $(cd "$path"; pwd) ; else [...]
"$(dirname $(dirname $(realpath $0)))"
ça marche, alors besoin de quelque chose d'autre ...echo
ne doit pas non plus être perpétré...
les références parentes avant de résoudre les liens symboliques, pas après; essayez ceci avec homebrewcoreutils
installé, créez un lien avecln -s /var/log /tmp/linkexample
puis exécutezrealpath /tmp/linkexample/../
; cela imprime/private/var
. Mais votre fonction produit à la/tmp/linkexample/..
place, carpwd
apparaît toujours/tmp/linkexample
après le cd.Sur macOS, la seule solution que j'ai trouvée pour gérer les liens symboliques de manière fiable consiste à utiliser
realpath
. Puisque cela l'exigebrew install coreutils
, je viens d'automatiser cette étape. Ma mise en œuvre ressemble à ceci:Ces erreurs s'ils ne sont pas
brew
installés, mais vous pouvez également l'installer également. Je ne me sentais tout simplement pas à l'aise d'automatiser quelque chose qui boucle du code ruby arbitraire à partir du net.Notez qu'il s'agit d'une variante automatisée de la réponse d' Oleg Mikheev .
Un test important
Un bon test de l'une de ces solutions est:
ln -s
) vers ce fichierLa solution déréférencera-t-elle le lien symbolique et vous donnera-t-elle le répertoire d'origine? Si c'est le cas, cela fonctionne.
la source
Cela semble fonctionner pour OSX, ne nécessite aucun binaire et a été extrait d'ici
la source
J'aime ça:
la source
J'avais besoin d'un
realpath
remplacement sur OS X, un qui fonctionne correctement sur les chemins avec des liens symboliques et des références parentales comme lereadlink -f
ferait . Cela inclut la résolution des liens symboliques dans le chemin avant de résoudre les références parent; Par exemple, si vous avez installé lacoreutils
bouteille homebrew , exécutez:Notez que cela
readlink -f
a été résolu/tmp/linkeddir
avant de résoudre la..
référence de répertoire parent. Bien sûr, il n'y areadlink -f
sur Mac soit .Donc, dans le cadre de l'implémentation a bash pour
realpath
j'ai réimplémenté ce qu'un appel decanonicalize_filename_mode(path, CAN_ALL_BUT_LAST)
fonction GNUlib fait , dans Bash 3.2; c'est aussi l'appel de fonction que GNUreadlink -f
fait:Il inclut la détection de lien symbolique circulaire, sortant si le même chemin (intermédiaire) est vu deux fois.
Si tout ce dont vous avez besoin est
readlink -f
, vous pouvez utiliser ce qui précède comme:Pour
realpath
, j'ai aussi besoin--relative-to
et le--relative-base
soutien, ce qui vous donne des chemins relatifs après canonisant:J'ai inclus des tests unitaires dans ma demande de révision de code pour ce code .
la source
Sur la base de la communication avec le commentateur, j'ai convenu qu'il était très difficile et qu'il n'y avait aucun moyen trival d'implémenter un realpath se comporte totalement comme Ubuntu.
Mais la version suivante peut gérer les cas d'angle, la meilleure réponse ne peut pas et satisfaire mes besoins quotidiens sur macbook. Mettez ce code dans votre ~ / .bashrc et rappelez-vous:
la source
echo
. Faitpwd
la même chose queecho $(pwd)
sans avoir à générer une deuxième copie du shell. De plus, ne pas citer l'argumentecho
est un bogue (vous perdrez tous les espaces de début ou de fin, tous les espaces blancs internes adjacents, et les caractères génériques sont développés, etc.). Voir plus sur stackoverflow.com/questions/10067266/…realpath
répertoire d'un répertoire inexistant.dir=$(dirname "$1"); file=$(basename "$1")
souci de cohérence, préférez probablement à la syntaxe de backtick obsolète depuis longtemps. Notez également la citation correcte des arguments, encore une fois.