680 Stimmen

Unix-Shell-Skript herausfinden, in welchem Verzeichnis sich die Skriptdatei befindet?

Grundsätzlich muss ich das Skript mit Pfaden ausführen, die sich auf den Speicherort der Shell-Skriptdatei beziehen. Wie kann ich das aktuelle Verzeichnis in das gleiche Verzeichnis ändern, in dem sich die Skriptdatei befindet?

15 Stimmen

Ist das wirklich ein Duplikat? In dieser Frage geht es um ein "Unix-Shell-Skript", in der anderen speziell um Bash.

3 Stimmen

@BoltClock: Diese Frage wurde fälschlicherweise geschlossen. In der verlinkten Frage geht es um Bash. In dieser Frage geht es um Unix-Shell-Programmierung. Beachten Sie, dass die akzeptierten Antworten sehr unterschiedlich sind!

0 Stimmen

@Dietrich Epp: Sie haben Recht. Es scheint, dass die Wahl der akzeptierten Antwort durch den Fragesteller und die Hinzufügung des [bash]-Tags (wahrscheinlich als Reaktion darauf) mich dazu veranlasst hat, die Frage als Antwort auf eine Markierung als Duplikat zu kennzeichnen.

747voto

TheMarko Punkte 7984

In Bash sollten Sie so bekommen, was Sie brauchen:

#!/usr/bin/env bash

BASEDIR=$(dirname "$0")
echo "$BASEDIR"

28 Stimmen

Dies funktioniert nicht, wenn Sie das Skript über einen symbolischen Link in einem anderen Verzeichnis aufgerufen haben. Damit das funktioniert, müssen Sie readlink auch (siehe Al's Antwort unten)

59 Stimmen

In der Bash ist es sicherer, die Option $BASH_SOURCE anstelle von $0 denn $0 enthält nicht immer den Pfad des aufzurufenden Skripts, z. B. wenn ein Skript "ausgelagert" wird.

7 Stimmen

$BASH_SOURCE ist Bash-spezifisch, die Frage bezieht sich auf Shell-Skripte im Allgemeinen.

507voto

al. Punkte 4685

Der ursprüngliche Beitrag enthält die Lösung (ignorieren Sie die Antworten, sie tragen nichts Nützliches bei). Die interessante Arbeit wird von dem erwähnten Unix-Befehl erledigt readlink mit Option -f . Funktioniert, wenn das Skript sowohl mit einem absoluten als auch mit einem relativen Pfad aufgerufen wird.

Für bash, sh, ksh:

#!/bin/bash 
# Absolute path to this script, e.g. /home/user/bin/foo.sh
SCRIPT=$(readlink -f "$0")
# Absolute path this script is in, thus /home/user/bin
SCRIPTPATH=$(dirname "$SCRIPT")
echo $SCRIPTPATH

Für tcsh, csh:

#!/bin/tcsh
# Absolute path to this script, e.g. /home/user/bin/foo.csh
set SCRIPT=`readlink -f "$0"`
# Absolute path this script is in, thus /home/user/bin
set SCRIPTPATH=`dirname "$SCRIPT"`
echo $SCRIPTPATH

Siehe auch: https://stackoverflow.com/a/246128/59087

0 Stimmen

Das ist der beste Weg. Beachten Sie, dass die Antwort "checked" nicht funktioniert, wenn Sie Folgendes tun: ./myscript.sh ... das würde melden, dass das Verzeichnis "." ist - dies wird Ihnen immer den absoluten Pfad liefern

14 Stimmen

Hinweis: Nicht alle Systeme haben readlink . Deshalb habe ich empfohlen, pushd/popd (Built-Ins für Bash) zu verwenden.

29 Stimmen

Die -f Option zu readlink macht etwas anderes unter OS X (Lion) und möglicherweise BSD. stackoverflow.com/questions/1055671/

71voto

Daniel Punkte 1745

Ein früherer Kommentar zu einer Antwort sagte es, aber es ist leicht zu übersehen unter all den anderen Antworten.

Bei Verwendung von bash:

echo this file: "$BASH_SOURCE"
echo this dir: "$(dirname "$BASH_SOURCE")"

Bash-Referenzhandbuch, 5.2 Bash-Variablen

3 Stimmen

Nur dieser funktioniert mit dem Skript im Umgebungspfad, die meisten anderen funktionieren nicht. Danke!

0 Stimmen

Sie sollten Folgendes verwenden dirname "$BASH_SOURCE" um Leerzeichen in $BASH_SOURCE zu behandeln.

1 Stimmen

Ein expliziterer Weg, das Verzeichnis zu drucken, wäre laut dem Tool ShellCheck folgender: "$(dirname "${BASH_SOURCE{0}}")", da BASH_SOURCE ein Array ist, und ohne den tiefgestellten Index wird standardmäßig das erste Element genommen.

55voto

Mez Punkte 23443

Angenommen, Sie verwenden die Bash

#!/bin/bash

current_dir=$(pwd)
script_dir=$(dirname "$0")

echo $current_dir
echo $script_dir

Dieses Skript sollte das Verzeichnis ausgeben, in dem Sie sich befinden, und dann das Verzeichnis, in dem sich das Skript befindet. Wenn Sie es zum Beispiel von / mit dem Skript in /home/mez/ gibt er aus

/
/home/mez

Denken Sie daran, dass Sie, wenn Sie Variablen aus der Ausgabe eines Befehls zuweisen, den Befehl in $( y ) - sonst erhalten Sie nicht das gewünschte Ergebnis.

4 Stimmen

Dies funktioniert nicht, wenn ich das Skript vom aktuellen Verzeichnis aus aufrufe.

7 Stimmen

@EricWang Sie sind immer im aktuellen Verzeichnis.

1 Stimmen

Für mich ist $current_dir tatsächlich der Pfad, von dem aus ich das Skript aufrufe. Allerdings ist $script_dir nicht das Verzeichnis des Skripts, es ist nur ein Punkt.

47voto

Die beste Antwort auf diese Frage wurde hier gegeben:
Abrufen des Quellverzeichnisses eines Bash-Skripts aus einer

Und das ist sie:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Einzeiler, der den vollständigen Verzeichnisnamen des Skripts angibt, egal von wo aus es aufgerufen wird.

Um zu verstehen, wie es funktioniert, können Sie das folgende Skript ausführen:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"

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