Gibt es eine Möglichkeit für ein bezogenes Shell-Skript, den Pfad zu sich selbst herauszufinden? Ich beschäftige mich hauptsächlich mit Bash, obwohl ich einige Mitarbeiter habe, die tcsh verwenden.
Ich vermute, dass ich hier nicht viel Glück haben kann, da durch das Sourcing Befehle in der aktuellen Shell ausgeführt werden. Es handelt sich also $0
immer noch um den Aufruf der aktuellen Shell, nicht um das Skript, von dem die Quelle stammt. Mein bester Gedanke ist derzeit zu tun source $script $script
, damit der erste Positionsparameter die notwendigen Informationen enthält. Hat jemand einen besseren Weg?
Um es klar auszudrücken , ich verwende das Skript und führe es nicht aus:
source foo.bash
Antworten:
In
tcsh
,$_
am Anfang des Skripts wird die Position enthält , wenn die Datei bezogen wurde und$0
enthält es , wenn es ausgeführt wurde.In Bash:
quelle
> tcsh --version\n tcsh 6.14.00 (Astron) 2005-03-25 (i486-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec
. Soweit es nicht interaktiv beschafft wird, wird die Quelldatei in die übergeordnete Datei aufgenommen, als wäre sie tatsächlich ein Teil davon (nicht zu unterscheiden), wie Sie in Ihrer ursprünglichen Frage erwähnt haben. Ich denke, Ihre Problemumgehung für Positionsparameter ist wahrscheinlich der beste Ansatz. Die übliche Frage lautet jedoch "Warum möchten Sie das tun?" Und die übliche Antwort lautet "Tun Sie das nicht - tun Sie dies stattdessen", wo "dies" häufig aufbewahrt wird ....
undsource
diesbezüglich identisch gearbeitet habe. Beachten Sie, dass$_
in der ersten Anweisung in der Datei zugegriffen werden muss , da sonst das letzte Argument des vorherigen Befehls enthalten ist. Ich mag es, den Shebang zu meiner eigenen Referenz hinzuzufügen, damit ich weiß, für welche Shell er gedacht ist und für den Editor, damit er Syntax-Hervorhebungen verwendet.source
, dann getan habe.
. Ich entschuldige mich für die Inkompetenz. Sie sind in der Tat identisch. Wie auch immer,$BASH_SOURCE
funktioniert.Ich denke, dass Sie
$BASH_SOURCE
Variable verwenden könnten . Es gibt den Pfad zurück, der ausgeführt wurde:Im nächsten Schritt sollten wir also prüfen, ob der Pfad relativ ist oder nicht. Wenn es nicht relativ ist, ist alles in Ordnung. Wenn ja, können wir den Pfad
pwd
mit/
und überprüfen , verketten$BASH_SOURCE
.quelle
source
gesucht wird,$PATH
wenn der angegebene Name kein. Enthält/
. Die Suchreihenfolge hängt von den Shell-Optionen ab. Weitere Informationen finden Sie im Handbuch.mydir="$(cd "$(dirname "$BASH_SOURCE")"; pwd)"
würde so etwas funktionieren?Aus Gründen der Gründlichkeit und zum Wohle der Suchenden tun diese Folgendes: Es handelt sich um ein Community-Wiki. Sie können also auch andere Shell-Entsprechungen hinzufügen ($ BASH_SOURCE ist natürlich anders).
test.sh:
test2.sh:
Bash:
Strich
Zsh
quelle
called=$_; echo $called; echo $_
? Wird das nicht$_
zweimal gedruckt ?$_
speziellen Parameter: "Setzen Sie beim Starten der Shell auf den absoluten Pfadnamen, der zum Aufrufen der Shell oder des Shell-Skripts verwendet wird, das in der Umgebungs- oder Argumentliste ausgeführt wird. Erweitert sich anschließend bis zum letzten Argument auf den vorherigen Befehl nach der Erweiterung. Wird auch auf den vollständigen Pfadnamen gesetzt, der zum Aufrufen jedes ausgeführten Befehls verwendet wird und in die für diesen Befehl exportierte Umgebung gestellt wird.#! /bin/sh
Quelldatei einen Header hat, der die Quelle unbrauchbar macht. Das würde eine neue Instanz von starten/bin/sh
, Variablen setzen und diese Instanz dann verlassen, wobei die aufrufende Instanz unverändert bleibt.#
in einem Shell-Skript beginnt, ist ein Kommentar.#!
(shebang) hat seine besondere Bedeutung nur als erste Zeile eines ausgeführten Skripts . Als erste Zeile einer Datei, die als Quelle dient, handelt es sich nur um einen Kommentar.Diese Lösung gilt nur für bash und nicht für tcsh. Beachten Sie, dass die häufig gelieferte Antwort
${BASH_SOURCE[0]}
nicht funktioniert, wenn Sie versuchen, den Pfad innerhalb einer Funktion zu finden.Ich habe festgestellt, dass diese Zeile immer funktioniert, unabhängig davon, ob die Datei als Quelle oder als Skript ausgeführt wird.
Wenn Sie Symlinks folgen möchten, verwenden Sie
readlink
auf dem Pfad, den Sie oben erhalten, rekursiv oder nicht rekursiv.Hier ist ein Skript, mit dem Sie es ausprobieren und mit anderen vorgeschlagenen Lösungen vergleichen können. Rufen Sie es als
source test1/test2/test_script.sh
oder aufbash test1/test2/test_script.sh
.Der Grund, warum der Einzeiler funktioniert, wird durch die Verwendung der
BASH_SOURCE
Umgebungsvariablen und ihrer assoziierten Elemente erklärtFUNCNAME
.[Quelle: Bash-Handbuch]
quelle
Dies funktionierte für mich in bash, dash, ksh und zsh:
Ausgabe für diese Shells:
Ich habe versucht, es für csh / tcsh zum Laufen zu bringen, aber es ist zu schwer. Ich halte mich an POSIX.
quelle
Die Community-Wiki-Antwort (von Shawn J. Goff) hat mich ein wenig verwirrt, deshalb habe ich ein Skript geschrieben, um die Dinge zu regeln. Über
$_
, fand ich dies: Verwendung_
als Umgebungsvariable an einen Befehl übergeben . Da es sich um eine Umgebungsvariable handelt, ist es einfach, ihren Wert falsch zu testen.Unten ist das Skript, dann wird es ausgegeben. Sie sind auch in diesem Kern .
test-shell-default-variables.sh
Ausgabe von
./test-shell-default-variables.sh {da,ba,z,k}sh
Was haben wir gelernt?
$BASH_SOURCE
$BASH_SOURCE
funktioniert in bash und nur in bash.$0
besteht darin, wann die aktuelle Datei von einer anderen Datei bezogen wurde.$BASH_PROFILE
Enthält in diesem Fall den Namen der Quelldatei und nicht den Namen der Quelldatei.$0
$0
den gleichen Wert wie$BASH_SOURCE
in bash.$_
$_
wird von dash und ksh unberührt gelassen.$_
zum letzten Argument des letzten Aufrufs.$_
auf "Bash" initialisiert .$_
unberührt. (bei der Beschaffung ist es nur das Ergebnis der Regel "letztes Argument").Symlinks
ksh
Sch
sh
wird, verhält es sich in Bezug auf diese Tests wie ein Bindestrich.quelle
Für die Bash-Shell fand ich die Antwort von @Dennis Williamson am hilfreichsten, aber im Fall von funktionierte sie nicht
sudo
. Das macht:quelle
Um Ihr Skript sowohl bash- als auch zsh-kompatibel zu machen, anstatt if-Anweisungen zu verwenden, können Sie einfach schreiben
${BASH_SOURCE[0]:-${(%):-%x}}
. Der resultierende Wert wirdBASH_SOURCE[0]
bei der Definition entnommen und${(%):-%x}}
wenn BASH_SOURCE [0] nicht definiert ist.quelle
tl; dr
script=$(readlink -e -- "${BASH_SOURCE}")
(für Bash offensichtlich)$BASH_SOURCE
Testfällegegebene Datei
/tmp/source1.sh
source
die Datei auf verschiedene Artensource
von/tmp
source
von/
source
aus verschiedenen relativen Pfaden/tmp/a
und/var
hinsichtlich
$0
in allen Fällen, wenn das Skript den hinzugefügten Befehl hatte
dann wird
source
das Skript immer gedrucktjedoch , wenn das Skript wurde ausgeführt , zB
dann
$0
wäre string value/tmp/source1.sh
.quelle
Diese Antwort beschreibt, wie
lsof
und ein bisschen Grep-Magie die einzige Möglichkeit zu sein scheint, mit verschachtelten Quelldateien unter tcsh zu arbeiten:quelle
Möglicherweise funktioniert dies nicht mit Symlinks oder Quelldateien, sondern für normale Dateien. Als Referenz hergenommen. @kenorb Kein Dirname, Readlink, BASH_SOURCE.
quelle
$0
Sie Informationen zum aktuell ausgeführten Skript erhalten, nicht zu einem Skript mit Quellenangabe."Dirname $ 0" gibt Ihnen den Pfad zum Skript, aber Sie müssen ihn ein wenig interpretieren:
Sie müssen sich darauf vorbereiten, mit "." als Verzeichnisname unter bestimmten Umständen. Ich würde ein bisschen experimentieren, da ich mich daran erinnere, dass der in ksh integrierte Dirname die Dinge ein bisschen anders macht, wenn "." erscheint in PATH.
quelle
$0
Enthält einfach "bash" für eine interaktive Shell und das ist alles, was das Skript sieht.