Wywołanie skryptu za pomocą ./bla.sh vs. bla.sh

11

Czy ktoś może mi wyjaśnić, co robi skorupa w dwóch przykładach A) i B) poniżej? Oczywiście zachowuje się inaczej, ale nie mogę się dowiedzieć, dlaczego wynik jest inny.

Przykład:
niech skrypt w naszym bieżącym katalogu ma nazwę bla.shtylko jednej komendy:
echo ${0##/*} hello

A)
Rozpoczęty jako: ./bla.sh
daje:./bla.sh hello

B)
Rozpoczęty jako: . bla.sh
daje:-bash hello

Ponieważ używam tego w skrypcie, drugie wyjście (z powodu „-” przed -bash) zabija polecenie. Oczywiście prosty --przed ${...}pomógł, ale chciałbym zrozumieć, co powoduje wynik w pierwszej kolejności.
Uwielbiam bash. I vi [m]. Ale dygresję…

Wilk
źródło

Odpowiedzi:

22
./bla.sh

Oto polecenie ./bla.sh. Powoduje to, że powłoka szuka pliku wykonywalnego o nazwie bla.shw bieżącym katalogu, a następnie prosi jądro o uruchomienie go jako normalnego programu, w innym procesie niż powłoka. (Nie ma znaczenia, czy bla.shjest to bashskrypt, perlczy pythonjeden, czy skompilowany plik binarny).


. bla.sh

Tutaj polecenie to .(aka source), wbudowane polecenie twojej powłoki. Powoduje, że powłoka szuka pliku o nazwie podanej bla.shw ścieżce systemowej ($ PATH) i interpretuje zawartość tak, jakbyś ją wpisał; wszystko to odbywa się w tym samym procesie co sama powłoka (a zatem może wpływać na wewnętrzny stan powłoki).

Działa to oczywiście tylko wtedy, gdy bla.shzawiera polecenia bashpowłoki (jeśli właśnie tego używasz), nie będzie działać dla perlskryptów ani niczego innego.

(Jest to wyjaśnione help .i help sourceza).


Ponieważ .i ./są to zupełnie różne rzeczy (polecenie vs część ścieżki), można je oczywiście łączyć - użycie . ./bla.shspowoduje „źródło” pliku bla.shw bieżącym katalogu.


Zazwyczaj najlepiej jest użyć tej ./bla.shmetody. Tylko ~/.bashrc, ~/.profilea takie pliki są zwykle pochodzą, bo oni mają modyfikować bieżące środowisko.

użytkownik1686
źródło
3
Ponadto, jeśli zmienisz środowisko bash w bla.sh, zmiany te zostaną uwzględnione później. bla.sh, ale nie po ./bla.sh. to dlatego, że . bla.sh działa w kontekście bieżącego basha, podczas gdy ./bla.sh działa jako podproces.
mouviciel
1
Zobacz także mywiki.wooledge.org/BashFAQ/060, aby zobaczyć kilka przykładów. Zauważ, że sourcejest to alias bash ., a nie odwrotnie i sourcenie będzie działał w innych powłokach.
mrucci,
7

./<cmd>uruchomi <cmd>program znajdujący się w bieżącym katalogu w nowym (rozwidlonym) procesie. Musi być wykonywalny. A także czytelne, zaczyna się od #!.

. <cmd>spowoduje, że twoja bieżąca powłoka wykona skrypt powłoki, <cmd>który znajduje się w twoim $PATHlub bieżącym katalogu w bieżącym procesie powłoki. To musi być czytelne. Jest to alias polecenia powłoki source.

kmkaplan
źródło
-1 . <cmd>wyszuka program w, $PATHa jeśli nie zostanie znaleziony, to przeszuka bieżący katalog.
dogbane
@dogbane Racja, poprawiłem to.
kmkaplan,
FWIW, nie wszystkie muszle będą przeszukiwać cwd w celu znalezienia skryptu źródłowego. Zsh (przynajmniej z konfiguracją, którą mam) wymaga. ./cmd
bstpierre
1
@bstpierre To wydaje się być ruchomym gruntem. Odwołanie do POSIX, które mam, mówi, że „powłoka powinna używać ścieżki wyszukiwania określonej przez PATH” i „Niektóre starsze implementacje przeszukiwały bieżący katalog w poszukiwaniu pliku, nawet jeśli wartość PATH go nie zezwala”.
kmkaplan,
1

./cmd używa jawnej ścieżki ( ./- bieżący katalog) do pliku wykonywalnego. I nie trzeba zaczynać #!.

. cmd- (aka source) - wbudowane polecenie bash. Jedną z widocznych różnic w wykonywaniu sourcejest to, że może ustawić / zmodyfikować zmienną środowiskową bieżącej powłoki.

Leonid Wołyński
źródło
a dokładniej, sourcejest to tylko pseudonim bash .(który jest standardem)
user1686
Masz rację. Naprawiony.
Leonid Volnitsky