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.

35voto

docwhat Punkte 10953

Wenn Sie bash.... verwenden

#!/bin/bash

pushd $(dirname "${0}") > /dev/null
basedir=$(pwd -L)
# Use "pwd -P" for the path without links. man bash for more info.
popd > /dev/null

echo "${basedir}"

4 Stimmen

Sie können die pushd / popd con cd $(dirname "${0}") et cd - damit es auf anderen Shells funktioniert, wenn diese eine pwd -L .

0 Stimmen

Warum sollten Sie hier pushd und popd verwenden?

1 Stimmen

So muss ich das ursprüngliche Verzeichnis nicht in einer Variablen speichern. Das ist ein Muster, das ich oft in Funktionen und so verwende. Es lässt sich sehr gut verschachteln, was gut ist.

27voto

Rohith Punkte 1211

Wenn Sie das tatsächliche Skriptverzeichnis erhalten möchten (unabhängig davon, ob Sie das Skript über einen Symlink oder direkt aufrufen), versuchen Sie es:

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

Dies funktioniert sowohl unter Linux als auch unter macOS. Ich konnte nicht sehen, jemand hier erwähnen über realpath . Ich bin mir nicht sicher, ob dieser Ansatz irgendwelche Nachteile hat.

auf macOS, müssen Sie Folgendes installieren coreutils zu verwenden realpath . Beispiel: brew install coreutils .

0 Stimmen

Dies scheint gut auf POSIX-kompatiblen Shells wie ash et dash (z.B. auf Alpine Linux)

24voto

Ján Sáreník Punkte 1437

Machen wir daraus einen POSIX-Oneliner:

a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; BASEDIR=$(cd "$a"; pwd)

Getestet auf vielen Bourne-kompatiblen Shells, einschließlich der BSD-Shells.

Soweit ich weiß, bin ich der Autor, und ich habe es in den öffentlichen Bereich gestellt. Für weitere Informationen siehe: https://www.jasan.tk/posts/2017-05-11-posix_shell_dirname_replacement/

1 Stimmen

Wie geschrieben, cd: too many arguments wenn der Pfad Leerzeichen enthält, und gibt $PWD . (eine offensichtliche Lösung, die aber nur zeigt, wie viele Grenzfälle es tatsächlich gibt)

1 Stimmen

Würde hochgestuft. Bis auf den Kommentar von @michael, dass es mit Leerzeichen im Pfad nicht funktioniert... Gibt es eine Lösung für dieses Problem?

1 Stimmen

@spechter Ja, dafür gibt es eine Lösung. Siehe aktualisiert jasan.tk/posix/2017/05/11/posix_shell_dirname_replacement

23voto

ranamalo Punkte 247

Wie theMarko vorschlägt:

BASEDIR=$(dirname $0)
echo $BASEDIR

Dies funktioniert, es sei denn, Sie führen das Skript aus demselben Verzeichnis aus, in dem sich das Skript befindet; in diesem Fall erhalten Sie einen Wert von '.

Um dieses Problem zu umgehen, verwenden Sie:

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

if [ $script_dir = '.' ]
then
script_dir="$current_dir"
fi

Sie können nun in Ihrem Skript die Variable current_dir verwenden, um auf das Skriptverzeichnis zu verweisen. Dies kann jedoch immer noch zu Problemen mit Symlinks führen.

20voto

blueyed Punkte 25926
cd $(dirname $(readlink -f $0))

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