2009-01-07 4 views
10

Was ich tun möchte, ist, Einstellungen aus einer Datei in meine aktuelle interaktive Bash-Shell wie folgt aufzunehmen:Wie kann ein Bash-Skript das Verzeichnis kennen, in dem es installiert ist, wenn es stammt? Operator?

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

Das Problem ist, dass das .settings-Skript auch das "." Operator, um andere Dateien wie folgt einzuschließen:

. .extra_settings

Wie referenziere ich den relativen Pfad für .Extra_settings in der Datei .settings? Diese beiden Dateien werden immer im selben Verzeichnis gespeichert, aber der Pfad zu diesem Verzeichnis hängt davon ab, wo diese Dateien installiert wurden.

Der Operator kennt immer/path/to/some/dir/wie oben gezeigt. Wie kann die .settings-Datei das Verzeichnis kennen, in dem es installiert ist? Ich hätte lieber keinen Installationsprozess, der den Namen des installierten Verzeichnisses aufzeichnet.

Antwort

17

Ich glaube $(dirname "$BASH_SOURCE") wird tun, was Sie wollen, solange die Datei, die Sie Sourcing sind, ist nicht ein symbolischer Link.

Wenn die Datei, die Sie Sourcing kann eine Symlink sein, können Sie so etwas wie das tun nach dem wahren Verzeichnis zu erhalten:

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

Perfekt. $ (dirname "$ BASH_SOURCE") ist genau das was ich gesucht habe. Für meinen Zweck interessieren mich Symlinks nicht so sehr. Danke an alle, die geantwortet haben. Wirklich gute Antworten hier. – Gary

+8

Zum Auflösen von Symlinks können Sie einfach folgendes tun: 'dir = $ (dirname $ (readlink -f" $ BASH_SOURCE "))' –

0

Ich habe versucht, mit Varianten von $ (dirname $ 0) zu verwirren, aber es scheitert, wenn die .settings-Datei mit "." Enthalten ist. Wenn ich die .settings-Datei ausführte, anstatt sie einzuschließen, würde diese Lösung funktionieren. Stattdessen gibt $ (dirname $ 0) immer "." Zurück, was das aktuelle Verzeichnis bedeutet. Dies schlägt fehl, wenn Sie so etwas tun:

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

+0

hmm, schade. Ich habe keine Ahnung, dann –

2

Eine andere Sicht auf das Problem - wenn Sie "." um Umgebungsvariablen zu setzen, ein anderer Standard Weg, dies zu tun, ist die Skript echo variable Einstellung Befehle zu haben, zum Beispiel:

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

eval dann die Ausgabe:

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

Das ist, wie Pakete wie modules Arbeit . Auf diese Weise macht es auch einfach Schalen von sh abgeleitet zu unterstützen (X=...; export X) und csh (setenv X ...)

+0

Richtig, das ist, wie INN es tut. "innconfvar" (ich glaube, so heißt es) gibt die Konfigurationsvariablen als sh-, csh- oder perl-Befehle aus. –

+0

Ich mag diese Idee. Ich benutze es jedoch nicht, da die Nebenwirkungen die .settings-Datei noch unlesbarer machen würden, da sie bereits viele Fluchtsymbole enthält. Siehe unten. – Gary

0

diese Art von Arbeiten. Es funktioniert in dem Sinne, dass Sie die $ (dirname $ 0) -Syntax in der .settings-Datei verwenden können, um ihre Heimat zu bestimmen, da Sie dieses Skript in einer neuen Shell ausführen. Allerdings fügt es eine zusätzliche Schicht von Faltung, wo Sie Zeilen ändern müssen, wie:

export MYDATE=$(date) 

zu

echo "export MYDATE=\$(date)" 

Vielleicht ist dies der einzige Weg?

+0

Scheint, es würde auch die Komplexität erhöhen, wenn Sie in Shell-Funktionen suchen. (Ich suchte nach einem Weg, dies zu tun, der sowohl mit ksh als auch mit bash funktioniert ...) – mpontillo

6

Hier ist, was vielleicht eine elegante Lösung sein:

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

Dies wird jedoch nicht funktionieren, wenn Links Sourcing.In diesem Fall könnte tun ein

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

Be ware, die Arrays wie ${array[x]} nicht konform POSIX. Natürlich ist das Array BASH_SOURCE nur in Bash verfügbar.

+0

Warum sollte das '[0]' benötigt werden? @JasonDay hat es nicht in seiner Antwort. – asmeurer

+3

BASH_SOURCE ist ein Array, das den Aufruf-Stack darstellt, wobei das erste Element das aktuell ausgeführte Skript ist. –