Diese Lösung gilt nur für die Bash. Beachten Sie, dass die üblicherweise gelieferte Antwort ${BASH_SOURCE[0]}
wird nicht funktionieren, wenn Sie versuchen, den Pfad innerhalb einer Funktion zu finden.
Ich habe festgestellt, dass diese Zeile immer funktioniert, unabhängig davon, ob die Datei ausgelagert oder als Skript ausgeführt wird.
dirname ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
Wenn Sie Symlinks folgen wollen, verwenden Sie readlink
auf dem Pfad, den Sie oben erhalten haben, rekursiv oder nicht rekursiv.
Hier ist ein Skript, um es auszuprobieren und mit anderen vorgeschlagenen Lösungen zu vergleichen. Rufen Sie es auf als source test1/test2/test_script.sh
o bash test1/test2/test_script.sh
.
#
# Location: test1/test2/test_script.sh
#
echo $0
echo $_
echo ${BASH_SOURCE}
echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
cur_file="${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
cur_dir="$(dirname "${cur_file}")"
source "${cur_dir}/func_def.sh"
function test_within_func_inside {
echo ${BASH_SOURCE}
echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
}
echo "Testing within function inside"
test_within_func_inside
echo "Testing within function outside"
test_within_func_outside
#
# Location: test1/test2/func_def.sh
#
function test_within_func_outside {
echo ${BASH_SOURCE}
echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
}
Der Grund, warum der Einzeiler funktioniert, liegt in der Verwendung der BASH_SOURCE
Umgebungsvariable und ihre zugehörige FUNCNAME
.
BASH_SOURCE
Eine Array-Variable, deren Mitglieder die Namen der Quelldateien sind, in denen die entsprechenden Shell-Funktionsnamen in der Array-Variable FUNCNAME definiert sind. Die Shell-Funktion ${FUNCNAME[$i]} wird in der Datei ${BASH_SOURCE[$i]} definiert und von ${BASH_SOURCE[$i+1]} aufgerufen.
FUNCNAME
Eine Array-Variable, die die Namen aller Shell-Funktionen enthält, die sich derzeit im Aufrufstapel der Ausführung befinden. Das Element mit dem Index 0 ist der Name einer beliebigen aktuell ausgeführten Shell-Funktion. Das unterste Element (das Element mit dem höchsten Index) ist "main". Diese Variable existiert nur, wenn eine Shell-Funktion ausgeführt wird. Zuweisungen an FUNCNAME haben keine Wirkung und geben einen Fehlerstatus zurück. Wenn FUNCNAME nicht gesetzt wird, verliert sie ihre besonderen Eigenschaften, auch wenn sie anschließend zurückgesetzt wird.
Diese Variable kann mit BASH_LINENO und BASH_SOURCE verwendet werden. Jedes Element von FUNCNAME hat entsprechende Elemente in BASH_LINENO und BASH_SOURCE, um den Aufrufstapel zu beschreiben. Zum Beispiel wurde ${FUNCNAME[$i]} aus der Datei ${BASH_SOURCE[$i+1]} in Zeile ${BASH_LINENO[$i]} aufgerufen. Das Caller-Builtin zeigt den aktuellen Aufrufstapel anhand dieser Informationen an.
[Quelle: Bash-Handbuch]
91 Stimmen
Keine der derzeitigen Lösungen funktioniert, wenn es irgendwelche Zeilenumbrüche am Ende des Verzeichnisnamens - Sie werden von der Befehlssubstitution entfernt. Um dies zu umgehen, können Sie ein Nicht-Neuzeilen-Zeichen innerhalb der Befehlsersetzung anhängen -
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd && echo x)"
- und entfernen Sie es ohne Befehlssubstitution -DIR="${DIR%x}"
.94 Stimmen
@jpmc26 Es gibt zwei sehr häufige Situationen: Unfälle und Sabotage. Ein Skript sollte nicht auf unvorhersehbare Weise versagen, nur weil jemand, irgendwo, eine
mkdir $'\n'
.36 Stimmen
Wer Leute sein System auf diese Weise sabotieren lässt, sollte es nicht der Bash überlassen, solche Probleme zu erkennen... und schon gar nicht Leute einstellen, die zu solchen Fehlern fähig sind. Ich habe in den 25 Jahren, in denen ich die Bash benutze, noch nie erlebt, dass so etwas irgendwo passiert.... Deshalb gibt es Dinge wie Perl und Praktiken wie Taint Checking (ich werde wahrscheinlich dafür geflamed werden, dass ich das sage :)
79 Stimmen
Ich empfehle Ihnen, dies zu lesen Bash FAQ über das Thema.
0 Stimmen
"${PWD%/}/application"