944 Stimmen

Zuverlässiger Weg für ein Bash-Skript, den vollständigen Pfad zu sich selbst zu erhalten

Ich habe ein Bash-Skript, das seinen vollständigen Pfad kennen muss. Ich versuche, einen weitgehend kompatiblen Weg zu finden, um das zu tun, ohne mit relativen oder komisch aussehenden Pfaden zu enden. Ich brauche nur Bash zu unterstützen, nicht sh, csh, etc.

Was ich bis jetzt herausgefunden habe:

  1. Die akzeptierte Antwort auf Abrufen des Quellverzeichnisses eines Bash-Skripts aus Adressen, die den Pfad des Skripts über dirname $0 was in Ordnung ist, aber das kann zu einem relativ Pfad (wie . ), was ein Problem darstellt, wenn Sie Verzeichnisse im Skript ändern und der Pfad weiterhin auf das Skriptverzeichnis verweisen soll. Trotzdem, dirname wird ein Teil des Puzzles sein.

  2. Die akzeptierte Antwort auf Absoluter Pfad eines Bash-Skripts unter OS X (OS X-spezifisch, aber die Antwort funktioniert trotzdem) gibt eine Funktion an, die prüft, ob $0 relativ aussieht und, falls dies der Fall ist, vorangestellt wird $PWD dazu. Aber das Ergebnis kann immer noch relative Bits enthalten (obwohl es insgesamt absolut ist) - zum Beispiel, wenn das Skript t im Verzeichnis /usr/bin und Sie sind in /usr und Sie geben ein bin/../bin/t um es auszuführen (ja, das ist verworren), landet man bei /usr/bin/../bin als Verzeichnispfad für das Skript. Welche Werke ...aber...

  3. Le site readlink Lösung auf dieser Seite die wie folgt aussieht:

    # Absolute path to this script. /home/user/bin/foo.sh
    SCRIPT=$(readlink -f $0)
    # Absolute path this script is in. /home/user/bin
    SCRIPTPATH=`dirname $SCRIPT`

    Aber readlink ist nicht POSIX und die Lösung beruht offenbar auf GNUs readlink wo BSDs aus irgendeinem Grund nicht funktionieren (ich habe keinen Zugang zu einem BSD-ähnlichen System, um das zu überprüfen).

Es gibt also verschiedene Möglichkeiten, die aber alle ihre Tücken haben.

Was wäre ein besserer Weg? Wobei "besser" bedeutet:

  • Das gibt mir den absoluten Pfad.
  • Entfernt störende Teile, selbst wenn sie auf komplizierte Weise aufgerufen werden (siehe Kommentar zu Nr. 2 oben). (Z.B. wird der Pfad zumindest mäßig kanonisiert.)
  • Bezieht sich nur auf Bash-ismen oder Dinge, die mit ziemlicher Sicherheit in den meisten gängigen Varianten von *nix-Systemen (GNU/Linux, BSD und BSD-ähnlichen Systemen wie OS X usw.) enthalten sind.
  • Vermeidet, wenn möglich, den Aufruf externer Programme (z.B. bevorzugt Bash built-ins).
  • ( Aktualisiert danke für die Vorwarnung, welche ) Es muss keine Symlinks auflösen (mir wäre es sogar lieber, wenn es sie in Ruhe ließe, aber das ist keine Voraussetzung).

41voto

Matt Punkte 731

Verwendung:

SCRIPT_PATH=$(dirname `which $0`)

which gibt auf der Standardausgabe den vollständigen Pfad der ausführbaren Datei aus, die ausgeführt worden wäre, wenn das übergebene Argument an der Shell-Eingabeaufforderung eingegeben worden wäre (das ist der Inhalt von $0)

dirname entfernt das Nicht-Verzeichnis-Suffix aus einem Dateinamen.

Daher erhalten Sie den vollständigen Pfad des Skripts, unabhängig davon, ob der Pfad angegeben wurde oder nicht.

29voto

ypid Punkte 1570

Da realpath auf meinem Linux-System nicht standardmäßig installiert ist, funktioniert das Folgende bei mir:

SCRIPT="$(readlink --canonicalize-existing "$0")"
SCRIPTPATH="$(dirname "$SCRIPT")"

$SCRIPT enthält den tatsächlichen Dateipfad zum Skript und $SCRIPTPATH den tatsächlichen Pfad des Verzeichnisses, das das Skript enthält.

Bevor Sie dies verwenden, lesen Sie die Kommentare von diese Antwort .

19voto

gerardw Punkte 5059

Leicht zu lesen? Nachstehend finden Sie eine Alternative. Sie ignoriert Symlinks

#!/bin/bash
currentDir=$(
  cd $(dirname "$0")
  pwd
)

echo -n "current "
pwd
echo script $currentDir

Seit ich die obige Antwort vor ein paar Jahren gepostet habe, habe ich meine Praxis dahingehend weiterentwickelt, dass ich dieses linuxspezifische Paradigma verwende, das Symlinks korrekt behandelt:

ORIGIN=$(dirname $(readlink -f $0))

18voto

poussma Punkte 6765

Einfach:

BASEDIR=$(readlink -f $0 | xargs dirname)

Ausgefallene Operatoren sind nicht erforderlich.

15voto

kenorb Punkte 134883

Sie können versuchen, die folgende Variable zu definieren:

CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"

Oder Sie können die folgende Funktion in Bash ausprobieren:

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

Diese Funktion benötigt ein Argument. Wenn das Argument bereits einen absoluten Pfad enthält, wird er so gedruckt, wie er ist, andernfalls wird $PWD Variable + Argument Dateiname (ohne ./ Präfix).

Verwandt:

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