Existe-t-il un moyen pour un script shell source de connaître le chemin d'accès à lui-même? Je suis principalement concerné par bash, bien que certains de mes collègues utilisent tcsh.
Je suppose que je n'aurai peut-être pas beaucoup de chance ici, étant donné que le sourcing entraîne l'exécution des commandes dans le shell actuel. Il en va donc de $0
même que l'invocation du shell actuel et non le script sourced. Ma meilleure pensée est actuellement de faire source $script $script
, de sorte que le premier paramètre de position contienne les informations nécessaires. Quelqu'un a un meilleur moyen?
Pour être clair, je cherche le script, pas l'exécute:
source foo.bash
Réponses:
En
tcsh
,$_
au début du script contiendra l'emplacement si le fichier a été sourced et$0
contient si elle a été exécutée.Dans Bash:
la source
> tcsh --version\n tcsh 6.14.00 (Astron) 2005-03-25 (i486-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec
. En ce qui concerne la recherche de manière non interactive, le fichier source est inclus dans le fichier parent comme s'il en faisait réellement partie (indiscernablement) comme vous l'avez mentionné dans votre question d'origine. Je pense que votre solution de contournement des paramètres de position est probablement la meilleure approche. Cependant, la question habituelle est "pourquoi voulez-vous faire cela" et la réponse habituelle à la réponse est "ne faites pas cela - faites ceci à la place" où "ceci" est souvent à stocker ....
etsource
travaillé de manière identique à cet égard. Notez que vous$_
devez accéder à la première instruction du fichier, sinon elle contiendra le dernier argument de la commande précédente. J'aime inclure le shebang pour ma propre référence afin que je sache quel shell il est supposé être et pour l'éditeur, il utilise donc la coloration syntaxique.source
, puis ensuite.
. Je m'excuse d'être incompétent. Ils sont en effet identiques. En tout cas, ça$BASH_SOURCE
marche.Je pense que vous pourriez utiliser
$BASH_SOURCE
variable. Il retourne le chemin qui a été exécuté:Donc, à l'étape suivante, nous devrions vérifier si le chemin est relatif ou non. Si ce n'est pas relatif, tout va bien. Si c'est le cas, nous pourrions vérifier le chemin avec
pwd
, concaténer avec/
et$BASH_SOURCE
.la source
source
recherche$PATH
si le nom donné ne contient pas de/
. L'ordre de recherche dépend des options du shell. Reportez-vous au manuel pour plus de détails.mydir="$(cd "$(dirname "$BASH_SOURCE")"; pwd)"
marcherait?Par souci de rigueur et de souci des chercheurs, voici ce qu'ils font ... C'est un wiki de communauté, alors n'hésitez pas à ajouter les équivalents des autres shell (évidemment, $ BASH_SOURCE sera différent).
test.sh:
test2.sh:
Frapper:
Tiret
Zsh
la source
called=$_; echo $called; echo $_
? Cette impression ne sera-t-elle pas$_
deux fois?$_
paramètre spécial: "Au démarrage du shell, définissez le chemin absolu utilisé pour appeler le shell ou le script de shell exécuté, comme dans la liste d'environnement ou d'arguments. argument de la commande précédente, après le développement. Définit également le chemin complet utilisé pour appeler chaque commande exécutée et placée dans l'environnement exporté vers cette commande. Lors de la vérification du courrier, ce paramètre contient le nom du fichier courrier. "#! /bin/sh
qui le rend inutile à la source. Cela créerait une nouvelle instance de/bin/sh
, définir des variables, puis quitterait cette instance, en laissant l'instance appelante inchangée.#
un script shell est un commentaire.#!
(shebang) n’a sa signification particulière que comme première ligne d’un script exécuté. En tant que première ligne d'un fichier source, il ne s'agit que d'un commentaire.Cette solution s'applique uniquement à bash et non à tcsh. Notez que la réponse généralement fournie
${BASH_SOURCE[0]}
ne fonctionnera pas si vous essayez de trouver le chemin depuis une fonction.J'ai trouvé que cette ligne fonctionnait toujours, que le fichier soit recherché ou exécuté en tant que script.
Si vous souhaitez suivre les liens symboliques utilisés
readlink
sur le chemin que vous obtenez ci-dessus, de manière récursive ou non récursive.Voici un script pour l'essayer et le comparer à d'autres solutions proposées. Invoquez-le comme
source test1/test2/test_script.sh
oubash test1/test2/test_script.sh
.La raison pour laquelle one-liner fonctionne est expliquée par l'utilisation de la
BASH_SOURCE
variable d'environnement et de son associéFUNCNAME
.[Source: Manuel Bash]
la source
Cela a fonctionné pour moi en bash, dash, ksh et zsh:
Sortie pour ces coquilles:
J'ai essayé de le faire fonctionner pour csh / tcsh, mais c'est trop difficile; Je m'en tiens à POSIX.
la source
La réponse du wiki de la communauté (de Shawn J. Goff) me confondait un peu, alors j'ai écrit un script pour arranger les choses. À propos de
$_
, j’ai trouvé ceci: Utilisation de_
comme variable d’environnement transmise à une commande . C'est une variable d'environnement, il est donc facile de tester sa valeur de manière incorrecte.Vous trouverez ci-dessous le script, puis sa sortie. Ils sont aussi dans cette essence .
test-shell-default-variables.sh
Sortie de
./test-shell-default-variables.sh {da,ba,z,k}sh
Qu'avons-nous appris?
$BASH_SOURCE
$BASH_SOURCE
fonctionne à bash et seulement à bash.$0
est que le fichier actuel a été recherché par un autre fichier. Dans ce cas,$BASH_PROFILE
contient le nom du fichier source plutôt que celui du fichier source.$0
$0
a la même valeur que$BASH_SOURCE
dans bash.$_
$_
est laissé intact par dash et ksh.$_
décroît jusqu'au dernier argument du dernier appel.$_
sur "bash".$_
intacte. (lors du sourcing, c’est juste le résultat de la règle du "dernier argument").Liens symboliques
ksh
sh
sh
, en ce qui concerne ces tests, il se comporte comme un tiret.la source
Pour le shell bash, la réponse de @Dennis Williamson m'a été très utile, mais cela n'a pas fonctionné dans le cas de
sudo
. Cela fait:la source
Pour rendre votre script compatible avec bash et zsh au lieu d'utiliser des instructions if, vous pouvez simplement écrire
${BASH_SOURCE[0]:-${(%):-%x}}
. La valeur résultante sera prise à partir deBASH_SOURCE[0]
sa définition et de celle de${(%):-%x}}
BASH_SOURCE [0].la source
tl; dr
script=$(readlink -e -- "${BASH_SOURCE}")
(pour bash évidemment)$BASH_SOURCE
cas de testfichier donné
/tmp/source1.sh
source
le fichier de différentes manièressource
de/tmp
source
de/
source
de différents chemins relatifs/tmp/a
et/var
En ce qui concerne
$0
dans tous les cas, si le script avait la commande ajoutée
alors
source
le script toujours imprimécependant , si le script a été exécuté , par exemple
alors
$0
serait une valeur de chaîne/tmp/source1.sh
.la source
cette réponse décrit comment
lsof
et un peu de magie grep est la seule chose qui semble offrir une chance de travail pour les fichiers à source imbriquée sous tcsh:la source
Peut-être que cela ne fonctionnera pas avec des liens symboliques ou des fichiers sources mais fonctionnera pour des fichiers normaux. Pris comme référence @kenorb Non dirname, readlink, BASH_SOURCE.
la source
$0
vous donne des informations sur le script en cours d'exécution , et non sur un script source.En fait, "dirname $ 0" vous donnera le chemin du script, mais vous devez l'interpréter un peu:
Vous devez vous préparer à gérer "." comme nom de répertoire dans certaines circonstances courantes. J'essayais un peu, car je me souviens du nom de répertoire intégré à ksh qui fait les choses un peu différemment quand "." apparaît dans PATH.
la source
$0
contient simplement "bash" pour un shell interactif, et c'est tout ce que le script source voit.