Aufruf eines Skripts mit ./bla.sh vs. bla.sh

11

Kann mir jemand erklären, was die Shell in den beiden folgenden Beispielen A) und B) tut? Es verhält sich offensichtlich anders, aber ich kann nicht herausfinden, warum die Ausgabe anders ist.

Beispiel:
Lassen Sie uns ein Skript in unserem aktuellen Verzeichnis bla.shmit nur einem Befehl benennen :
echo ${0##/*} hello

A)
Begonnen als: ./bla.sh
gibt:./bla.sh hello

B)
Begonnen als: . bla.sh
gibt:-bash hello

Da ich dies in einem Skript verwende, bricht die zweite Ausgabe (wegen des "-" vor der -bash) den Befehl ab. Natürlich hat ein einfaches --vor dem ${...}geholfen, aber ich würde gerne verstehen, was die Ausgabe überhaupt verursacht.
Ich liebe Bash. Und vi [m]. Aber ich schweife ab…

Wolf
quelle

Antworten:

22
./bla.sh

Hier ist der Befehl ./bla.sh. Dadurch sucht die Shell nach einer ausführbaren Datei bla.shim aktuellen Verzeichnis und fordert den Kernel auf, sie als normales Programm in einem von der Shell getrennten Prozess auszuführen. (Es spielt keine Rolle, ob bla.shes sich um ein bashSkript, ein perloder ein Skript pythonoder eine kompilierte Binärdatei handelt.)


. bla.sh

Hier ist der Befehl .(aka source) ein eingebauter Befehl Ihrer Shell. Dadurch sucht die Shell nach einer Datei mit dem Namen bla.shim Systempfad ($ PATH) und interpretiert den Inhalt so, als ob er von Ihnen eingegeben worden wäre. All dies geschieht im selben Prozess wie die Shell selbst (und kann daher den internen Zustand der Shell beeinflussen).

Dies funktioniert natürlich nur, wenn bla.shBefehle für die bashShell enthalten sind (falls dies der Fall ist, den Sie gerade verwenden). Für perlSkripte oder andere Funktionen funktioniert dies nicht .

(Dies wird auch in help .und erklärt help source.)


Wie .und ./sind völlig verschiedene Dinge (ein Befehl vs Teil eines Pfades), können sie kombiniert werden , natürlich werden - mit . ./bla.shwürde „Quelle“ , um eine Datei bla.shim aktuellen Verzeichnis.


Normalerweise ist es am besten, die ./bla.shMethode zu verwenden. Nur ~/.bashrc, ~/.profileund solche Dateien werden in der Regel bezogen, weil sie die aktuelle Umgebung ändern sollen.

Grawity
quelle
3
Wenn Sie die Bash-Umgebung in bla.sh ändern, werden diese Änderungen nachträglich berücksichtigt. bla.sh aber nicht nach ./bla.sh. das ist weil . bla.sh wird im Kontext der aktuellen Bash ausgeführt, während ./bla.sh als Unterprozess ausgeführt wird.
mouviciel
1
Siehe auch mywiki.wooledge.org/BashFAQ/060 für einige Beispiele. Beachten Sie, dass dies sourceein Bash-Alias ​​für ist ., nicht das Gegenteil und sourcein anderen Shells nicht funktioniert.
Mrucci
7

./<cmd>Führt das <cmd>Programm, das sich im aktuellen Verzeichnis befindet, in einem neuen (gegabelten) Prozess aus. Es muss ausführbar sein. Und auch lesbar fängt es damit an #!.

. <cmd>veranlasst Ihre aktuelle Shell, das Shell-Skript auszuführen, das sich im aktuellen Shell-Prozess <cmd>in Ihrem $PATHoder im aktuellen Verzeichnis befindet . Es muss lesbar sein. Es ist ein Alias ​​für den Shell-Befehl .source

kmkaplan
quelle
-1 . <cmd>sucht nach dem Programm in $PATHund wenn es nicht gefunden wird, dann sucht es im aktuellen Verzeichnis.
Dogbane
@dogbane Richtig, ich habe das korrigiert.
kmkaplan
FWIW, nicht alle Shells durchsuchen cwd nach Quell-Skripten. zsh (zumindest mit der Konfiguration, die ich habe) erfordert. ./cmd
bstpierre
1
@bstpierre Dies scheint ein bewegender Boden zu sein. Die POSIX-Referenz, die ich habe, besagt, dass "die Shell den von PATH angegebenen Suchpfad verwenden soll" und "Einige ältere Implementierungen haben das aktuelle Verzeichnis nach der Datei durchsucht, auch wenn der Wert von PATH dies nicht
zuließ
1

./cmd Verwendet den expliziten Pfad ( ./- current dir) zur ausführbaren Datei. Und es ist nicht notwendig, dass es mit beginnt #!.

. cmd- (aka source) - Bash Builtin-Befehl. Ein sichtbarer Unterschied bei der Ausführung sourcebesteht darin, dass die Umgebungsvariable der aktuellen Shell festgelegt / geändert werden kann.

Leonid Volnitsky
quelle
genauer gesagt, sourceist ein Alias ​​für nur Bash .(was Standard ist)
Grawity
Du hast recht. Fest.
Leonid Volnitsky