2009-01-07 6 views
10

Ce que je voudrais faire est d'inclure les paramètres d'un fichier dans mon shell bash interactif actuel comme ceci:Comment un script bash peut-il connaître le répertoire dans lequel il est installé? opérateur?

$. /path/to/some/dir/.settings

Le problème est que le script .settings doit également utiliser le "." opérateur pour inclure d'autres fichiers comme celui-ci:

. .extra_settings

Comment est-ce que je référence le chemin relatif pour .extra_settings dans le fichier .settings? Ces deux fichiers sont toujours stockés dans le même répertoire, mais le chemin d'accès à ce répertoire sera différent en fonction de l'emplacement d'installation de ces fichiers.

L'opérateur connaît toujours/path/to/some/dir/comme indiqué ci-dessus. Comment le fichier .settings peut-il connaître le répertoire dans lequel il est installé? Je préférerais ne pas avoir un processus d'installation qui enregistre le nom du répertoire installé.

Répondre

17

Je crois que $(dirname "$BASH_SOURCE") va faire ce que vous voulez, tant que le fichier que vous Sourcing est pas un lien symbolique.

Si le fichier que vous sourcez peut être un lien symbolique, vous pouvez faire quelque chose comme ce qui suit pour obtenir le vrai répertoire:

PRG="$BASH_SOURCE" 
progname=`basename "$BASH_SOURCE"` 

while [ -h "$PRG" ] ; do 
    ls=`ls -ld "$PRG"` 
    link=`expr "$ls" : '.*-> \(.*\)$'` 
    if expr "$link" : '/.*' > /dev/null; then 
     PRG="$link" 
    else 
     PRG=`dirname "$PRG"`"/$link" 
    fi 
done 

dir=$(dirname "$PRG") 
+0

Parfait. $ (dirname "$ BASH_SOURCE") est ce que j'étais exactement ce que je cherchais. Pour mon but, je ne me soucie pas tellement des liens symboliques. Merci à tous ceux qui ont répondu. Vraiment de bonnes réponses ici. – Gary

+8

Pour résoudre les liens symboliques, vous pouvez simplement faire: 'dir = $ (dirname $ (readlink -f" $ BASH_SOURCE "))' –

0

J'ai essayé de jouer avec des variantes de $ (dirname $ 0) mais il échoue lorsque le fichier .settings est inclus avec ".". Si j'exécutais le fichier .settings au lieu de l'inclure, cette solution fonctionnerait. Au lieu de cela, le $ (dirname $ 0) retourne toujours ".", Ce qui signifie le répertoire courant. Cela échoue lorsque vous faites quelque chose comme ceci:

$ cd/ $. /some/path/.settings

+0

hmm, dommage. Je n'ai aucune idée alors –

2

Une approche différente du problème - si vous utilisez "." afin de définir des variables d'environnement, une autre façon standard pour le faire est d'avoir votre script écho des commandes de réglage variables, par exemple:

# settings.sh 
echo export CLASSPATH=${CLASSPATH}:/foo/bar 

Eval alors la sortie:

eval $(/path/to/settings.sh) 

Voilà comment les paquets comme modules travail . De cette façon, rend également facile à supporter des coquilles dérivées de poisson (X=...; export X) et csh (setenv X ...)

+0

Droit, c'est comme ça que le DCI le fait. "innconfvar" (je pense que c'est ce que l'on appelle) émet les variables de configuration en tant que commandes sh, csh ou perl. –

+0

J'aime cette idée. Cependant, je ne l'utilise pas parce que les effets secondaires rendraient le fichier .settings encore plus illisible car il a déjà beaucoup d'échappements pour commencer. Voir ci-dessous. – Gary

0

Ce genre d'œuvres. Cela fonctionne dans le sens où vous pouvez utiliser la syntaxe $ (dirname $ 0) dans le fichier .settings pour déterminer sa maison depuis que vous exécutez ce script dans un nouveau shell. Cependant, il ajoute une couche supplémentaire de convolution où vous devez changer des lignes telles que:

export MYDATE=$(date) 

à

echo "export MYDATE=\$(date)" 

Peut-être que c'est la seule façon?

+0

On dirait que cela ajouterait de la complexité si vous utilisiez des fonctions shell. (Je cherchais un moyen de faire cela qui fonctionne à la fois avec ksh et bash ...) – mpontillo

6

Voici ce qui pourrait être une solution élégante:

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

Ce ne sera pas, cependant, le travail lorsque les liens sourcing.Dans ce cas, on pourrait faire

script_dir=$(readlink -f $(readlink "${BASH_SOURCE[0]}") 

que les tableaux articles Soyez comme ${array[x]} ne sont pas conformes à POSIX. Bien sûr, le tableau BASH_SOURCE n'est disponible que dans Bash.

+0

Pourquoi le '[0]' serait-il nécessaire? @JasonDay ne l'a pas dans sa réponse. – asmeurer

+3

BASH_SOURCE est un tableau représentant la pile d'appels avec le premier élément étant le script en cours d'exécution. –

Questions connexes