805 votes

Façon fiable pour un script bash pour obtenir le chemin complet à lui-même?

J'ai un script bash qui a besoin de connaître son chemin d'accès complet. J'essaie de trouver un large compatible façon de le faire sans se retrouver avec une relative ou funky chemins. J'ai seulement besoin de soutien bash, pas de sh, csh, etc.

Ce que j'ai trouvé pour l'instant:

  1. La accepté de répondre à "Peut faire un script Bash dire ce répertoire, il est stocké dans?" adresses obtenir le chemin d'accès du script via dirname $0, ce qui est bien, mais que peut retourner une relative chemin (comme .), ce qui est un problème si vous voulez changer le répertoire de sauvegarde dans le script et le chemin reste du script d'annuaire. Encore, dirname sera une pièce du puzzle.

  2. La accepté de répondre à "script Bash chemin absolu avec OSX" (OS X, mais la réponse fonctionne indépendamment) donne une fonction qui permettra de tester pour voir si $0 semble relative, et si tel est pré-pend $PWD . Mais le résultat peut encore avoir par rapport bits (bien que dans l'ensemble c'est absolu) — par exemple, si le script est - t dans le répertoire /usr/bin et vous êtes en /usr et vous tapez bin/../bin/t pour l'exécuter (oui, c'est alambiqué), vous vous retrouvez avec /usr/bin/../bin comme le script du chemin d'accès au répertoire. Ce qui fonctionne, mais...

  3. L' readlink solution sur cette page, qui ressemble à ceci:

    # Absolute path to this script. /home/user/bin/foo.sh
    SCRIPT=$(readlink -f $0)
    # Absolute path this script is in. /home/user/bin
    SCRIPTPATH=`dirname $SCRIPT`
    

    Mais readlink n'est pas POSIX et, apparemment, la solution repose sur GNU - readlink où BSD ne fonctionne pas pour une raison quelconque (je n'ai pas accès à un BSD-like système pour vérifier).

Ainsi, les différentes façons de le faire, mais ils ont tous leurs mises en garde.

Ce serait une meilleure façon? Où "plus" signifie:

  • Donne-moi le chemin d'accès absolu.
  • Prend funky bits, même lorsqu'il est invoqué dans un alambiqué (voir commentaire n ° 2 ci-dessus). (E. g., au moins modérément canonicalizes le chemin.)
  • Ne repose que sur le coup-ismes ou des choses qui sont presque certain d'être sur la plus populaire des saveurs de systèmes *nix (GNU/Linux, BSD et BSD-like des systèmes tels que OS X, etc.).
  • Évite l'appel de programmes externes si possible (par exemple, préfère bash built-ins).
  • (Mise à jour, merci pour la tête, qui) N'a pas à résoudre les liens symboliques (en fait, je ferais en sorte de le préfèrent les a laissés seuls, mais ce n'est pas une obligation).

Merci à l'avance.

696voto

T.J. Crowder Points 285826

Pour répondre à ma propre question (par la FAQ)...

Voici ce que j'ai trouvé qui semble la plupart du temps de s'adapter à mon "mieux" critères:

pushd `dirname $0` > /dev/null
SCRIPTPATH=`pwd`
popd > /dev/null

...mais il semble rond-point et maladroit. J'espère que quelqu'un aura une meilleure réponse.

Notez également que ésotérique situations, telles que l'exécution d'un script qui n'est pas issu d'un fichier dans un système de fichiers accessible à tous (ce qui est parfaitement possible), n'est pas pris en charge à (ou dans l'une des autres réponses que j'ai vu).

Modifier: Modifier la deuxième ligne:

SCRIPTPATH=`pwd -P`

...si vous voulez résoudre des liens symboliques. (Je n'en ai pas, mais que d'autres.) Je ne sais pas comment largement pris en charge l' -P drapeau est bien.Dennis Williamson nous explique ci-dessous que -P est considéré comme fiable, bien, il y a longtemps. :-)

285voto

Je suis surpris que la commande realpath n'ait pas été mentionnée ici. Ma compréhension est que c'est largement portable / porté.

Votre solution initiale devient:

 SCRIPT=`realpath $0`
SCRIPTPATH=`dirname $SCRIPT`
 

Et pour laisser des liens symboliques non résolus selon votre préférence:

 SCRIPT=`realpath -s $0`
SCRIPTPATH=`dirname $SCRIPT`
 

201voto

Andrew Norrie Points 241

Le moyen le plus simple que j'ai trouvé pour obtenir un chemin canonique complet dans bash est d'utiliser cd et pwd :

 ABSOLUTE_PATH=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)/`basename "${BASH_SOURCE[0]}"`
 

L'utilisation de $ {BASH_SOURCE [0]} au lieu de $ 0 produit le même comportement que le script soit appelé <name> ou source <name>

60voto

Felix Rabe Points 1256

J'ai juste dû revoir ce numéro aujourd'hui et j'ai trouvé http://stackoverflow.com/a/246128/1034080 . Il élabore une solution que j'ai déjà utilisée par le passé .

 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 

Il y a plus de variantes à la réponse liée, par exemple pour le cas où le script lui-même est un lien symbolique.

41voto

GreenFox Points 489

Obtenir le chemin absolu du script shell

Ne pas utiliser -f option dans readlink, devrait donc fonctionner dans bsd/mac-osx

Prend en charge

  • source ./script (Lorsqu'il est appelé par l' . l'opérateur de point)
  • Chemin absolu /chemin/vers/le / script
  • Chemin d'accès relatif aime ./script
  • /chemin/dir1/../dir2/dir3/../script
  • Lorsqu'il est appelé à partir du lien symbolique
  • Lorsque le lien symbolique est imbriquée eg) foo->dir1/dir2/bar bar->./../doe doe->script
  • Lorsque l'appelant change le nom de scripts

Je suis à la recherche pour les cas particuliers où ce code ne fonctionne pas. S'il vous plaît laissez-moi savoir.

Code

pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}";
while([ -h "${SCRIPT_PATH}" ]); do
    cd "`dirname "${SCRIPT_PATH}"`"
    SCRIPT_PATH="$(readlink "`basename "${SCRIPT_PATH}"`")";
done
cd "`dirname "${SCRIPT_PATH}"`" > /dev/null
SCRIPT_PATH="`pwd`";
popd  > /dev/null
echo "srcipt=[${SCRIPT_PATH}]"
echo "pwd   =[`pwd`]"

Connu issuse

Le Script doit être quelque part sur le disque, que ce soit sur un réseau. Si vous essayez d'exécuter ce script à partir d'un TUYAU, elle ne fonctionnera pas

wget -o /dev/null -O - http://host.domain/dir/script.sh |bash

Techniquement parlant, il n'est pas défini.
Pratiquement parlant, il n'est pas sain d'esprit moyen de détecter cette. (co-processus ne peut pas accéder env du parent)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X