Zusammenfassung:
FULL_PATH_TO_SCRIPT="$(realpath "${BASH_SOURCE[-1]}")"
# OR, if you do NOT need it to work for **sourced** scripts too:
# FULL_PATH_TO_SCRIPT="$(realpath "$0")"
# OR, depending on which path you want, in case of nested `source` calls
# FULL_PATH_TO_SCRIPT="$(realpath "${BASH_SOURCE[0]}")"
# OR, add `-s` to NOT expand symlinks in the path:
# FULL_PATH_TO_SCRIPT="$(realpath -s "${BASH_SOURCE[-1]}")"
SCRIPT_DIRECTORY="$(dirname "$FULL_PATH_TO_SCRIPT")"
SCRIPT_FILENAME="$(basename "$FULL_PATH_TO_SCRIPT")"
Einzelheiten:
Wie erhält man die vollständiger Dateipfad , vollständiges Verzeichnis y Basisdateiname eines beliebigen Skripts laufen. OR bezogen ...
...auch wenn das aufgerufene Skript aus einer anderen Bash-Funktion oder einem Skript heraus aufgerufen wird, oder wenn verschachteltes Sourcing verwendet wird!
In vielen Fällen brauchen Sie nur den vollständigen Pfad zu dem Skript, das Sie gerade aufgerufen haben. Dies kann leicht erreicht werden mit realpath
. Beachten Sie, dass realpath
ist Teil von GNU coreutils . Wenn Sie es nicht bereits installiert haben (bei Ubuntu ist es standardmäßig installiert), können Sie es mit sudo apt update && sudo apt install coreutils
.
get_script_path.sh (die neueste Version dieses Skripts finden Sie unter get_script_path.sh in meinem eRCaGuy_hello_world repo):
#!/bin/bash
# A. Obtain the full path, and expand (walk down) symbolic links
# A.1. `"$0"` works only if the file is **run**, but NOT if it is **sourced**.
# FULL_PATH_TO_SCRIPT="$(realpath "$0")"
# A.2. `"${BASH_SOURCE[-1]}"` works whether the file is sourced OR run, and even
# if the script is called from within another bash function!
# NB: if `"${BASH_SOURCE[-1]}"` doesn't give you quite what you want, use
# `"${BASH_SOURCE[0]}"` instead in order to get the first element from the array.
FULL_PATH_TO_SCRIPT="$(realpath "${BASH_SOURCE[-1]}")"
# B.1. `"$0"` works only if the file is **run**, but NOT if it is **sourced**.
# FULL_PATH_TO_SCRIPT_KEEP_SYMLINKS="$(realpath -s "$0")"
# B.2. `"${BASH_SOURCE[-1]}"` works whether the file is sourced OR run, and even
# if the script is called from within another bash function!
# NB: if `"${BASH_SOURCE[-1]}"` doesn't give you quite what you want, use
# `"${BASH_SOURCE[0]}"` instead in order to get the first element from the array.
FULL_PATH_TO_SCRIPT_KEEP_SYMLINKS="$(realpath -s "${BASH_SOURCE[-1]}")"
# You can then also get the full path to the directory, and the base
# filename, like this:
SCRIPT_DIRECTORY="$(dirname "$FULL_PATH_TO_SCRIPT")"
SCRIPT_FILENAME="$(basename "$FULL_PATH_TO_SCRIPT")"
# Now print it all out
echo "FULL_PATH_TO_SCRIPT = \"$FULL_PATH_TO_SCRIPT\""
echo "SCRIPT_DIRECTORY = \"$SCRIPT_DIRECTORY\""
echo "SCRIPT_FILENAME = \"$SCRIPT_FILENAME\""
WICHTIGER Hinweis zu verschachtelt source
ruft auf. : wenn "${BASH_SOURCE[-1]}"
nicht das gewünschte Ergebnis liefert, versuchen Sie es mit "${BASH_SOURCE[0]}"
stattdessen. Die erste ( 0
) gibt Ihnen den ersten Eintrag im Array, und der letzte ( -1
) gibt Ihnen den letzten Eintrag im Array. Je nachdem, wonach Sie suchen, möchten Sie vielleicht den ersten Eintrag. Ich entdeckte, dass dies der Fall war, als ich ~/.bashrc
con . ~/.bashrc
die aus dem ~/.bash_aliases
con . ~/.bash_aliases
und ich wollte die realpath
(mit erweiterten Symlinks) zum ~/.bash_aliases
Datei, NICHT in die ~/.bashrc
Datei. Da es sich um verschachtelt source
Anrufe, mit "${BASH_SOURCE[0]}"
gab mir, was ich wollte: den erweiterten Weg zu ~/.bash_aliases
! Verwendung von "${BASH_SOURCE[-1]}"
gab mir jedoch, was ich tat ノット wollen: den erweiterten Pfad zu ~/.bashrc
.
Beispielbefehl und -ausgabe:
-
Laufen das Drehbuch:
~/GS/dev/eRCaGuy_hello_world/bash$ ./get_script_path.sh
FULL_PATH_TO_SCRIPT = "/home/gabriel/GS/dev/eRCaGuy_hello_world/bash/get_script_path.sh"
SCRIPT_DIRECTORY = "/home/gabriel/GS/dev/eRCaGuy_hello_world/bash"
SCRIPT_FILENAME = "get_script_path.sh"
-
Beschaffung das Skript mit . get_script_path.sh
o source get_script_path.sh
(das Ergebnis ist genau dasselbe wie oben, weil ich die "${BASH_SOURCE[-1]}"
im Skript anstelle von "$0"
):
~/GS/dev/eRCaGuy_hello_world/bash$ . get_script_path.sh
FULL_PATH_TO_SCRIPT = "/home/gabriel/GS/dev/eRCaGuy_hello_world/bash/get_script_path.sh"
SCRIPT_DIRECTORY = "/home/gabriel/GS/dev/eRCaGuy_hello_world/bash"
SCRIPT_FILENAME = "get_script_path.sh"
Wenn Sie "$0"
im Skript anstelle von "${BASH_SOURCE[-1]}"
erhalten Sie die gleiche Ausgabe wie oben, wenn läuft das Skript, aber das Unerwünschte ausgegeben, wenn Beschaffung das Drehbuch:
~/GS/dev/eRCaGuy_hello_world/bash$ . get_script_path.sh
FULL_PATH_TO_SCRIPT = "/bin/bash"
SCRIPT_DIRECTORY = "/bin"
SCRIPT_FILENAME = "bash"
Und, wenn Sie die "$BASH_SOURCE"
anstelle von "${BASH_SOURCE[-1]}"
wird es ノット funktionieren, wenn das Skript aus einer anderen Bash-Funktion heraus aufgerufen wird. Also, mit "${BASH_SOURCE[-1]}"
ist daher der beste Weg, da er diese beiden Probleme löst! Siehe die Referenzen unten.
Der Unterschied zwischen realpath
y realpath -s
:
Beachten Sie, dass realpath
geht auch erfolgreich symbolische Links ab, um ihre Ziele zu bestimmen und auf sie zu zeigen, anstatt auf den symbolischen Link zu zeigen. Wenn Sie dieses Verhalten NICHT wollen (manchmal will ich das nicht), dann fügen Sie -s
zum realpath
Befehl, so dass die Zeile stattdessen wie folgt aussieht:
# Obtain the full path, but do NOT expand (walk down) symbolic links; in
# other words: **keep** the symlinks as part of the path!
FULL_PATH_TO_SCRIPT="$(realpath -s "${BASH_SOURCE[-1]}")"
Auf diese Weise werden symbolische Links NICHT erweitert. Sie werden vielmehr so belassen, wie sie sind, als symbolische Links im vollständigen Pfad.
Der obige Code ist jetzt Teil meiner eRCaGuy_hello_world Repo in dieser Datei hier: bash/get_script_path.sh . Verweisen Sie auf diese Datei und führen Sie sie aus, um vollständige Beispiele sowohl mit als auch ohne Symlinks in den Pfaden zu erhalten. Am Ende der Datei finden Sie Beispielausgaben für beide Fälle.
Referenzen:
- Abrufen des absoluten Pfads bei relativem Pfad
- lehrte mich über die
BASH_SOURCE
variabel: Unix & Linux: Ermitteln des Pfads zum gesourcten Shell-Skript
- lehrte mich, dass
BASH_SOURCE
ist eigentlich ein Array, und wir wollen das letzte Element daraus, damit es innerhalb einer Funktion wie erwartet funktioniert (deshalb habe ich "${BASH_SOURCE[-1]}"
in meinem Code hier): Unix & Linux: Ermittlung des Pfades zum gesourcten Shell-Skript
-
man bash
--> Suche nach BASH_SOURCE
:
BASH_SOURCE
Eine Array-Variable, deren Mitglieder die Namen der Quelldateien sind, in denen die entsprechenden Shell-Funktionsnamen in der FUNCNAME
Array-Variable definiert sind. Die Shell-Funktion ${FUNCNAME[$i]}
ist definiert in der Datei ${BASH_SOURCE[$i]}
und aufgerufen von ${BASH_SOURCE[$i+1]}
.
Siehe auch:
- (meine Antwort) Unix & Linux: Ermitteln des Pfads zum gesourcten Shell-Skript
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"