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

-3voto

Ich möchte sicherstellen, dass das Skript in seinem Verzeichnis ausgeführt wird. Also

cd $(dirname $(which $0) )

Wenn Sie danach wirklich wissen wollen, wo Sie sich befinden, führen Sie den folgenden Befehl aus.

DIR=$(/usr/bin/pwd)

6 Stimmen

Wie unterscheidet sich dies von anderen Antworten?

-4voto

Andry Punkte 1591

Es gibt keinen 100% portablen und zuverlässigen Weg, um einen Pfad zu einem aktuellen Skriptverzeichnis abzufragen. Insbesondere zwischen verschiedenen Backends wie Cygwin , MinGW , MSYS Linux, etc. Dieses Problem wurde in der Bash seit Ewigkeiten nicht richtig und vollständig gelöst.

Dies könnte zum Beispiel nicht gelöst werden, wenn Sie den Pfad nach der source Befehl, um ein anderes Bash-Skript einzubinden, das seinerseits denselben source um ein anderes Bash-Skript einzubinden und so weiter.

Im Falle der source zu verwenden, schlage ich vor, den Befehl source Befehl mit etwas wie diesem:

function include()
{
  if [[ -n "$CURRENT_SCRIPT_DIR" ]]; then
    local dir_path=... get directory from `CURRENT_SCRIPT_DIR/$1`, depends if $1 is absolute path or relative ...
    local include_file_path=...
  else
    local dir_path=... request the directory from the "$1" argument using one of answered here methods...
    local include_file_path=...
  fi
  ... push $CURRENT_SCRIPT_DIR in to stack ...
  export CURRENT_SCRIPT_DIR=... export current script directory using $dir_path ...
  source "$include_file_path"
  ... pop $CURRENT_SCRIPT_DIR from stack ...
}

Von nun an wird die Verwendung von include(...) stützt sich auf frühere CURRENT_SCRIPT_DIR in Ihrem Skript.

Dies funktioniert nur, wenn Sie alle source Befehle von include Befehl. Wenn Sie das nicht können, dann haben Sie keine Wahl. Zumindest solange, bis die Entwickler des Bash-Interpreters einen expliziten Befehl zur Abfrage des aktuellen Skriptverzeichnisses bereitstellen.

Meine eigene Umsetzung kommt dem am nächsten: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/bash/tacklelib/bash_tacklelib
https://github.com/andry81/tacklelib/tree/trunk/bash/tacklelib/bash_tacklelib

(Suche nach dem tkl_include Funktion)

-4voto

MatteoBee Punkte 61

Das habe ich im Laufe der Jahre gebastelt, um es als Kopfzeile für meine Bash-Skripte zu verwenden:

## BASE BRAIN - Get where you're from and who you are.
MYPID=$$
ORIGINAL_DIR="$(pwd)" # This is not a hot air balloon ride..
fa="$0" # First Assumption
ta= # Temporary Assumption
wa= # Weighed Assumption
while true; do
    [ "${fa:0:1}" = "/" ] && wa=$0 && break
    [ "${fa:0:2}" = "./" ] && ta="${ORIGINAL_DIR}/${fa:2}" && [ -e "$ta" ] && wa="$ta" && break
    ta="${ORIGINAL_DIR}/${fa}" && [ -e "$ta" ] && wa="$ta" && break
done
SW="$wa"
SWDIR="$(dirname "$wa")"
SWBIN="$(basename "$wa")"
unset ta fa wa
( [ ! -e "$SWDIR/$SWBIN" ] || [ -z "$SW" ] ) && echo "I could not find my way around :( possible bug in the TOP script" && exit 1

Zu diesem Zeitpunkt enthalten Ihre Variablen SW, SWDIR und SWBIN alles, was Sie brauchen.

0 Stimmen

Ein guter Kandidat für einen Code-Obscurity-Wettbewerb. Anstelle von ORIGINAL_DIR können Sie PWD und was bedeutet MYPID mit der Antwort überhaupt zu tun hat?

-6voto

danemacmillan Punkte 1162

Le site gewählte Antwort funktioniert sehr gut. Ich veröffentliche meine Lösung für alle, die nach kürzeren Alternativen suchen, die dennoch Sourcing, Executing, vollständige Pfade, relative Pfade und Symlinks berücksichtigen. Schließlich funktioniert dies auf macOS da nicht davon ausgegangen werden kann, dass die Version der GNU coreutils von readlink ist verfügbar.

Der Haken an der Sache ist, dass es nicht die Bash verwendet, aber es ist einfach, in einem Bash-Skript zu verwenden. Obwohl der Auftraggeber keine Einschränkungen bezüglich der Sprache der Lösung gemacht hat, ist es wahrscheinlich das Beste, dass die meisten in der Bash-Welt geblieben sind. Dies ist nur eine Alternative, und möglicherweise eine unpopuläre.

PHP ist auf macOS standardmäßig verfügbar und wird auch auf einer Reihe anderer Plattformen installiert, allerdings nicht unbedingt standardmäßig. Mir ist klar, dass dies ein Manko ist, aber ich lasse das hier trotzdem für alle, die von Suchmaschinen kommen.

export SOURCE_DIRECTORY="$(php -r 'echo dirname(realpath($argv[1]));' -- "${BASH_SOURCE[0]}")"

3 Stimmen

In der Frage ging es nicht um MacOS. Ich denke, diese Antwort sollte mit "Ein anderer Ansatz ist die Verwendung von PHP, anstatt sich auf BASH zu verlassen" beginnen. Denn dies zeigt sich erst am Ende der Antwort.

-7voto

Paul Savage Punkte 21
FOLDERNAME=${PWD##*/}

Das ist der schnellste Weg, den ich kenne.

5 Stimmen

Dies beginnt einfach mit pwd und gibt nicht den Pfad zurück, in dem sich das aktuell ausgeführte Skript befindet.

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