Ich habe viele der gegebenen Antworten verglichen und habe einige kompaktere Lösungen gefunden. Diese scheinen alle verrückten Randfälle zu behandeln, die sich aus Ihrer Lieblingskombination von ergeben:
- Absolute Pfade oder relative Pfade
- Datei und Verzeichnis Softlinks
- Anrufung als
script
, bash script
, bash -c script
, source script
, oder . script
- Leerzeichen, Tabulatoren, Zeilenumbrüche, Unicode, usw. in Verzeichnissen und/oder Dateinamen
- Dateinamen, die mit einem Bindestrich beginnen
Wenn Sie von Linux aus arbeiten, scheint es, dass die Verwendung der proc
Handle ist die beste Lösung, um die vollständig aufgelöste Quelle des aktuell laufenden Skripts zu finden (in einer interaktiven Sitzung verweist der Link auf die entsprechende /dev/pts/X
):
resolved="$(readlink /proc/$$/fd/255 && echo X)" && resolved="${resolved%$'\nX'}"
Das ist zwar ein wenig hässlich, aber die Lösung ist kompakt und leicht verständlich. Wir verwenden nicht nur Bash-Primitive, aber das ist in Ordnung, denn readlink
vereinfacht diese Aufgabe erheblich. Die echo X
fügt eine X
an das Ende der Variablen-Zeichenkette, damit nachstehende Leerzeichen im Dateinamen nicht gefressen werden, und die Parametersubstitution ${VAR%X}
am Ende der Zeile wird die X
. Denn readlink
einen eigenen Zeilenumbruch hinzufügt (der normalerweise in der Befehlssubstitution gefressen würde, wenn nicht unser vorheriger Trick angewendet worden wäre), müssen wir auch diesen loswerden. Dies lässt sich am einfachsten mit der Option $''
Zitierschema, das uns die Verwendung von Escape-Sequenzen wie \n
um Zeilenumbrüche darzustellen (auf diese Weise können Sie auch leicht Verzeichnisse und Dateien mit abwegigen Namen erstellen).
Die obigen Angaben sollten Ihre Bedürfnisse abdecken, um das aktuell laufende Skript unter Linux zu finden, aber wenn Sie nicht die proc
Dateisystem zur Verfügung haben, oder wenn Sie versuchen, den vollständig aufgelösten Pfad einer anderen Datei zu finden, dann finden Sie vielleicht den folgenden Code hilfreich. Es ist nur eine kleine Abwandlung des obigen Einzeilers. Wenn Sie mit seltsamen Verzeichnis-/Dateinamen herumspielen, überprüfen Sie die Ausgabe mit beiden ls
y readlink
ist informativ, da ls
gibt "vereinfachte" Pfade aus und ersetzt ?
für Dinge wie Zeilenumbrüche.
absolute_path=$(readlink -e -- "${BASH_SOURCE[0]}" && echo x) && absolute_path=${absolute_path%?x}
dir=$(dirname -- "$absolute_path" && echo x) && dir=${dir%?x}
file=$(basename -- "$absolute_path" && echo x) && file=${file%?x}
ls -l -- "$dir/$file"
printf '$absolute_path: "%s"\n' "$absolute_path"
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"