2009-01-07 10 views
10

Quello che mi piacerebbe fare è includere le impostazioni da un file nella mia attuale shell interattiva bash come questa:Come può uno script di bash conoscere la directory in cui è installato al momento dell'acquisto. operatore?

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

Il problema è che anche lo script .settings deve utilizzare "." operatore per includere altri file come questo:

. .extra_settings

Come riferimento il percorso relativo per .extra_settings nel file .settings? Questi due file sono sempre memorizzati nella stessa directory, ma il percorso di questa directory sarà diverso a seconda di dove sono stati installati questi file.

L'operatore conosce sempre/path/to/some/dir/come mostrato sopra. Come può il file .settings conoscere la directory in cui è installato? Preferirei non avere un processo di installazione che registra il nome della directory installata.

risposta

17

Credo $(dirname "$BASH_SOURCE") farà quello che vuoi, a patto che il file che si sono sourcing è non un link simbolico.

Se il file che si sono sourcing può essere un link simbolico, si può fare qualcosa di simile a quanto segue per ottenere il vero directory:

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

Perfetto. $ (dirname "$ BASH_SOURCE") è quello che ero esattamente quello che stavo cercando. Per il mio scopo, non mi interessa molto dei collegamenti simbolici. Grazie a tutti coloro che hanno risposto. Davvero buone risposte qui. – Gary

+8

Per risolvere i collegamenti simbolici è sufficiente fare: 'dir = $ (nome_destinazione $ (readlink -f" $ BASH_SOURCE "))' –

0

Ho provato a modificare le varianti di $ (dirname $ 0) ma non riesce quando il file .settings è incluso in ".". Se stavo eseguendo il file .settings invece di includerlo, questa soluzione funzionerebbe. Invece, $ (dirname $ 0) restituisce sempre ".", Che significa directory corrente. Questo non riesce quando si fa qualcosa di simile:

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

+0

hmm, peccato. non ho idea quindi –

2

Un approccio diverso al problema, se si sta utilizzando "." al fine di impostare le variabili d'ambiente, un altro modo standard per fare questo è di avere lo script eco comandi di regolazione variabile, ad esempio:

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

quindi eval l'output:

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

Ecco come pacchetti come modules lavoro . In questo modo rende anche più facile da sostenere conchiglie derivati ​​da sh (X=...; export X) e csh (setenv X ...)

+0

Giusto, è così che l'INN lo fa. "innconfvar" (penso sia quello che viene chiamato) emette le variabili di configurazione come comandi sh, csh o perl. –

+0

Mi piace questa idea. Tuttavia, non lo sto usando perché gli effetti collaterali renderebbero il file .settings ancora più illeggibile poiché ha già un sacco di escape per cominciare. Vedi sotto. – Gary

0

Questo tipo di opere. Funziona nel senso che puoi usare la sintassi $ (dirname $ 0) all'interno del file .settings per determinare la sua home poiché stai eseguendo questo script in una nuova shell. Tuttavia, si aggiunge un ulteriore livello di circonvoluzione in cui è necessario cambiare linee come:

export MYDATE=$(date) 

a

echo "export MYDATE=\$(date)" 

Forse questo è l'unico modo?

+0

Sembra che aggiungerebbe anche complessità se si eseguisse il sourcing nelle funzioni di shell. (Stavo cercando un modo per farlo che funzioni sia con ksh che con bash ...) – mpontillo

6

Ecco quello che potrebbe essere una soluzione elegante:

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

Questo, tuttavia, non opera nell'acquisto di collegamenti.In tal caso, si potrebbe fare

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

articoli che gli array come ${array[x]} non sono POSIX compliant. Ovviamente, l'array BASH_SOURCE è disponibile solo in Bash.

+0

Perché sarebbe necessario il '[0]'? @ JasonDay non ce l'ha nella sua risposta. – asmeurer

+3

BASH_SOURCE è una matrice che rappresenta lo stack di chiamate con il primo elemento rappresentato dallo script attualmente in esecuzione. –

Problemi correlati