Se référer à un fichier relatif à l'exécution du script

94

Dans un script bash que j'écris, j'utilise sourcepour inclure la variable définie dans un fichier de configuration. Le script à exécuter est act.sh, tandis que le script à être sourced est act.conf.sh, donc dans act.shj'ai:

source act.conf.sh

Cependant, cela ne fonctionne que lors de l'exécution act.shdans le répertoire le contenant, car act.conf.shil fait référence au fichier placé sous le répertoire de travail. Existe-t-il une solution pour faire référence au fichier relatif au script en cours d'exécution sans l'invoquer cd? Merci.

Ryan Li
la source

Réponses:

116

Voir: Entrée FAQ BASH n ° 28: "Comment déterminer l'emplacement de mon script? Je veux lire certains fichiers de configuration à partir du même endroit."

Aucune solution ne fonctionnera à 100%:

Il est important de réaliser que dans le cas général, ce problème n'a pas de solution. Toute approche dont vous avez peut-être entendu parler, et toute approche qui sera détaillée ci-dessous, présente des défauts et ne fonctionnera que dans des cas spécifiques. Avant tout, essayez d'éviter complètement le problème en ne dépendant pas de l'emplacement de votre script!

Si vous avez besoin d'écrire un outil très réutilisable, alors prendre le chemin correct comme paramètre de votre script sera la méthode la plus fiable .

En supposant que votre script ne sera exécuté qu'à partir de certains shells, et seulement avec un peu de flexibilité nécessaire, vous pouvez probablement relâcher une partie de cette paranoïa. Il est toujours bon de regarder vos options. Les gens utilisent des modèles courants qui sont particulièrement problématiques.

En particulier, la FAQ recommande d'éviter la $0variable très couramment utilisée :

Rien de ce qui lit $0ne sera jamais à l'épreuve des balles, car $0lui-même n'est pas fiable.

Comme alternative, vous pouvez utiliser à la $BASH_SOURCEplace. Quelque chose comme ça:

source "${BASH_SOURCE%/*}/act.conf.sh"

Cette solution comporte également quelques mises en garde. Consultez la page FAQ pour voir les compromis entre les différentes solutions. Ils semblent recommander cden combinaison avec $BASH_SOURCEdans les cas où cela fonctionnera pour vous, car vous obtenez une condition d'erreur pratique lorsqu'il ne se développe pas correctement.

Ignacio Vazquez-Abrams
la source
1
Merci, j'utiliserais readlink. N'a pas été en mesure de déterminer les mots-clés à rechercher, alors j'ai posé la question ici ....
Ryan Li
9
Pouvez-vous insérer les informations pertinentes dans la réponse au cas où la FAQ bash serait en panne?
Merlyn Morgan-Graham
3
Link recommande:, cd "${BASH_SOURCE%/*}" || exitou read somevar < "${BASH_SOURCE%/*}/etc/somefile", Link décourage fortement $0 "Rien qui lit $ 0 ne sera jamais à l'épreuve des balles, car $ 0 lui-même n'est pas fiable."
ThorSummoner
10
Que fait le% / * après BASH_SOURCE et comment?
Silicomancer
34

Voir ceci: Bash: Comment _best_ inclure d'autres scripts?

Je suggère d'utiliser:

source $(dirname $0)/act.conf.sh
vagovszkym
la source
8
Ce n'est pas la réponse que vous recherchez. $0est intrinsèquement bogué. Voir la réponse la plus votée et acceptée pour savoir pourquoi, ou lisez simplement mywiki.wooledge.org/BashFAQ/028 - une courte solution de contournement pour la question posée est quelque chose commesource "${BASH_SOURCE%/*}/act.conf.sh"
Merlyn Morgan-Graham
5

Essayez ce qui suit:

source ${BASH_SOURCE[0]/%act.sh/act.conf.sh}
Aucune idée
la source