6176 Stimmen

Wie kann ich das Quellverzeichnis eines Bash-Skripts aus dem Skript selbst abrufen?

Wie erhalte ich den Pfad des Verzeichnisses, in dem ein Bash Skript befindet sich, innerhalb dieses Drehbuch?

Ich möchte ein Bash-Skript als Launcher für eine andere Anwendung verwenden. Ich möchte das Arbeitsverzeichnis in das Verzeichnis ändern, in dem sich das Bash-Skript befindet, damit ich mit den Dateien in diesem Verzeichnis arbeiten kann:

$ ./application

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 :)

142voto

Mr Shark Punkte 24994

Sie können verwenden $BASH_SOURCE :

#!/bin/bash

scriptdir=`dirname "$BASH_SOURCE"`

Beachten Sie, dass Sie die #!/bin/bash y no #!/bin/sh da es eine Bash-Erweiterung ist.

19 Stimmen

Wenn ich das tue ./foo/script entonces $(dirname $BASH_SOURCE) es ./foo .

4 Stimmen

@Till, In diesem Fall können wir verwenden realpath Befehl, um den vollständigen Pfad von ./foo/script zu erhalten. Also dirname $(realpath ./foo/script) gibt den Pfad des Skripts an.

1 Stimmen

Backticks sind veraltet. Verwenden Sie stattdessen Dollarparen -- $(...) .

126voto

Fabien Punkte 6258

Kurze Antwort:

`dirname $0`

oder ( vorzugsweise ):

$(dirname "$0")

24 Stimmen

Es wird nicht funktionieren, wenn Sie das Skript als Quelle angeben. "source my/script.sh"

0 Stimmen

Ich verwende dies ständig in meinen Bash-Skripten, die Dinge automatisieren und oft andere Skripte im selben Verzeichnis aufrufen. Ich würde niemals source über diese und cd $(dirname $0) ist leicht zu merken.

21 Stimmen

@vidstige: ${BASH_SOURCE[0]} anstelle von $0 arbeitet mit source my/script.sh

119voto

Simon Rigét Punkte 2417

Das sollte genügen:

DIR="$(dirname "$(realpath "$0")")"

Dies funktioniert mit Symlinks und Leerzeichen im Pfad.

Bitte lesen Sie die Man Pages für dirname y realpath .

Bitte fügen Sie einen Kommentar hinzu, wie Sie MacOS unterstützen können. Es tut mir leid, ich kann es überprüfen.

10 Stimmen

Mit Ihrer Lösung, indem Sie das Skript wie folgt aufrufen ./script.sh zeigt . anstelle des vollständigen Verzeichnispfads

6 Stimmen

Es gibt keine -f Option für readlink unter MacOS. Verwenden Sie stat stattdessen. Aber dennoch zeigt es . wenn Sie sich in 'diesem' Verzeichnis befinden.

3 Stimmen

Sie müssen Folgendes installieren coreutils von Homebrew und verwenden greadlink um die -f Option unter MacOS, da es sich unter der Haube um *BSD und nicht um Linux handelt.

76voto

SpoonMeiser Punkte 19191

pwd kann verwendet werden, um das aktuelle Arbeitsverzeichnis zu finden, und dirname um das Verzeichnis einer bestimmten Datei zu finden (der Befehl, der ausgeführt wurde, ist $0 also dirname $0 sollte Ihnen das Verzeichnis des aktuellen Skripts anzeigen).

Allerdings, dirname gibt genau den Verzeichnisteil des Dateinamens an, der höchstwahrscheinlich relativ zum aktuellen Arbeitsverzeichnis sein wird. Wenn Ihr Skript aus irgendeinem Grund das Verzeichnis wechseln muss, dann ist die Ausgabe von dirname wird bedeutungslos.

Ich schlage Folgendes vor:

#!/bin/bash

reldir=`dirname $0`
cd $reldir
directory=`pwd`

echo "Directory is $directory"

Auf diese Weise erhalten Sie ein absolutes und nicht ein relatives Verzeichnis.

Da das Skript in einer separaten Bash-Instanz ausgeführt wird, ist es nicht notwendig, das Arbeitsverzeichnis anschließend wiederherzustellen, aber wenn Sie aus irgendeinem Grund in Ihrem Skript zurückwechseln möchten, können Sie einfach den Wert von pwd in eine Variable einfügen, bevor Sie das Verzeichnis wechseln, um es später zu verwenden.

Obwohl nur

cd `dirname $0`

das spezifische Szenario in der Frage löst, finde ich die Angabe des absoluten Pfads generell nützlicher.

12 Stimmen

Sie können das alles in einer Zeile wie dieser machen: DIRECTORY=$(cd dirname $0 && pwd)

1 Stimmen

Dies funktioniert nicht, wenn das Skript ein anderes Skript als Quelle verwendet und Sie den Namen des letzteren wissen wollen.

43voto

P M Punkte 817
SCRIPT_DIR=$( cd ${0%/*} && pwd -P )

0 Stimmen

Das ist viel kürzer als die gewählte Antwort. Und sie scheint genauso gut zu funktionieren. Sie verdient 1000 Stimmen, nur damit sie nicht übersehen wird.

6 Stimmen

Wie in vielen der vorangegangenen Antworten ausführlich erläutert wurde, sind weder $0 ni pwd haben garantiert die richtigen Informationen, je nachdem, wie das Skript aufgerufen wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X