Verweis auf eine Datei in Bezug auf die Ausführung eines Skripts

90

In einem Bash-Skript, das ich schreibe, verwende ich source, um die in einer Konfigurationsdatei definierte Variable einzuschließen. Das auszuführende Skript ist act.sh, während das auszuführende Skript sourced ist act.conf.sh, also habe act.shich in:

source act.conf.sh

Dies funktioniert jedoch nur, wenn es act.shin dem Verzeichnis ausgeführt wird, in dem es enthalten ist, da act.conf.shdort auf die Datei verwiesen wird, die sich unter dem Arbeitsverzeichnis befindet. Gibt es eine Lösung, um auf die Datei relativ zum ausgeführten Skript zu verweisen, ohne sie aufzurufen cd? Vielen Dank.

Ryan Li
quelle

Antworten:

112

Siehe: BASH FAQ-Eintrag Nr. 28: "Wie bestimme ich den Speicherort meines Skripts? Ich möchte einige Konfigurationsdateien von derselben Stelle aus lesen."

Jede Lösung wird nicht 100% der Zeit funktionieren:

Es ist wichtig zu wissen, dass dieses Problem im allgemeinen Fall keine Lösung hat. Jeder Ansatz, von dem Sie vielleicht schon gehört haben, und jeder Ansatz, der im Folgenden beschrieben wird, weist Mängel auf und funktioniert nur in bestimmten Fällen. Versuchen Sie in erster Linie, das Problem vollständig zu vermeiden, indem Sie nicht vom Speicherort Ihres Skripts abhängen!

Wenn Sie ein sehr wiederverwendbares Tool schreiben müssen, ist es die zuverlässigste Methode, den richtigen Pfad als Parameter für Ihr Skript zu verwenden .

Angenommen, Ihr Skript wird nur von bestimmten Shells ausgeführt und nur mit ein wenig Flexibilität können Sie wahrscheinlich einen Teil dieser Paranoia lockern. Es ist immer noch gut, sich Ihre Optionen anzusehen. Es gibt gängige Muster, die Menschen verwenden und die besonders problematisch sind.

In den häufig gestellten Fragen wird insbesondere empfohlen, die häufig verwendete $0Variable zu vermeiden :

Nichts, was liest, $0wird jemals kugelsicher sein, weil es $0selbst unzuverlässig ist.

Alternativ können Sie $BASH_SOURCEstattdessen verwenden. Etwas wie das:

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

Auch bei dieser Lösung gibt es einige Einschränkungen. Auf der FAQ-Seite finden Sie die Kompromisse zwischen verschiedenen Lösungen. Sie scheinen cdin Kombination mit $BASH_SOURCEin Fällen zu empfehlen, in denen es für Sie funktioniert, da Sie eine praktische Fehlerbedingung erhalten, wenn es nicht richtig erweitert wird.

Ignacio Vazquez-Abrams
quelle
1
Danke, ich würde verwenden readlink. Konnte nicht die Schlüsselwörter bestimmen, nach denen gesucht werden soll, also postete die Frage hier ....
Ryan Li
8
Können Sie die relevanten Informationen in die Antwort einfließen lassen, falls die Bash-FAQ nicht funktioniert?
Merlyn Morgan-Graham
3
Link empfiehlt: cd "${BASH_SOURCE%/*}" || exitoder read somevar < "${BASH_SOURCE%/*}/etc/somefile"Link stark entmutigt $0 "Nichts, das $ 0 liest, wird jemals kugelsicher sein, weil $ 0 selbst unzuverlässig ist."
ThorSummoner
9
Was macht% / * nach BASH_SOURCE und wie?
Silicomancer
32

Siehe dies: Bash: Wie kann ich andere Skripte am besten einschließen?

Ich schlage vor zu verwenden:

source $(dirname $0)/act.conf.sh
vagovszkym
quelle
7
Dies ist nicht die Antwort, die Sie suchen. $0ist von Natur aus fehlerhaft. Sehen Sie sich die am besten gewählte und akzeptierte Antwort an, warum, oder lesen Sie einfach mywiki.wooledge.org/BashFAQ/028 - kurze Problemumgehung für die gestellte Frage ist so etwas wiesource "${BASH_SOURCE%/*}/act.conf.sh"
Merlyn Morgan-Graham
4

Versuche Folgendes:

source ${BASH_SOURCE[0]/%act.sh/act.conf.sh}
Ahnungslos
quelle