Вызов сценария с ./bla.sh против. bla.sh

11

Кто-нибудь может объяснить мне, что делает оболочка в двух примерах А) и Б) ниже? Это очевидно ведет себя по-разному, но я не могу выяснить, почему результат отличается.

Пример:
у нас будет скрипт в нашем текущем каталоге, названный bla.shтолько одной командой:
echo ${0##/*} hello

А) Начинается
как: ./bla.sh
дает:./bla.sh hello

Б)
Начинается как: . bla.sh
дает:-bash hello

Поскольку я использую это в скрипте, второй вывод (из-за "-" перед -bash) убивает команду. Конечно, простое --раньше ${...}помогло, но мне бы очень хотелось понять, чем обусловлен выход в первую очередь.
Я люблю Баш. И ви [м]. Но я отвлекся ...

волк
источник

Ответы:

22
./bla.sh

Здесь команда есть ./bla.sh. Это заставляет оболочку искать исполняемый файл с именем bla.shв текущем каталоге, а затем просит ядро ​​запустить его как обычную программу, в отдельном процессе от оболочки. (Неважно, bla.shявляется ли bashскрипт скриптом a perlили pythonone или скомпилированным двоичным файлом.)


. bla.sh

Здесь команда .(aka source) - встроенная команда вашей оболочки. Это заставляет оболочку искать файл с именем bla.shв системном пути ($ PATH) и интерпретировать содержимое, как если бы оно было напечатано вами; все это делается в том же процессе, что и сама оболочка (и, следовательно, может влиять на внутреннее состояние оболочки).

Это, конечно, работает только тогда, когда bla.shсодержит команды для bashоболочки (если это та, которую вы сейчас используете), она не будет работать для perlскриптов или чего-либо еще.

(Это объясняется help .и help sourceтоже.)


Так как .и ./это совершенно разные вещи (команда против части пути), их можно, конечно, комбинировать - используя . ./bla.sh«источник» файла bla.shв текущем каталоге.


Обычно лучше всего использовать ./bla.shметод. Только ~/.bashrc, ~/.profileи такие файлы, как правило , поступают, потому что они должны изменить текущую среду.

user1686
источник
3
Более того, если вы измените среду bash в bla.sh, эти изменения будут учтены после. бла.ш, но не после ./bla.sh. это потому что . Bla.sh работает в контексте текущего bash, тогда как ./bla.sh работает как подпроцесс.
mouviciel
1
См. Также mywiki.wooledge.org/BashFAQ/060 для некоторых примеров. Обратите внимание, что sourceэто псевдоним bash ., а не наоборот, и sourceон не будет работать в других оболочках.
mrucci
7

./<cmd>выполнит <cmd>программу, находящуюся в текущем каталоге, в новом (разветвленном) процессе. Это должно быть исполняемым. И также читается это начинается с #!.

. <cmd>заставит вашу текущую оболочку выполнить сценарий оболочки, <cmd>который находится в вашем $PATHили текущем каталоге в текущем процессе оболочки. Это должно быть читабельным. Это псевдоним для команды оболочки source.

kmkaplan
источник
-1 . <cmd>будет искать программу в, $PATHи если она не найдена, то она будет искать в текущем каталоге.
Догбейн
@ Dogbane Правильно, я исправил это.
kmkaplan
FWIW, не все оболочки будут искать cwd для поиска скриптов. zsh (по крайней мере, с моим . ./cmd
конфигом
1
@bstpierre Кажется, это движущаяся площадка. У меня есть ссылка на POSIX, в которой говорится, что «оболочка должна использовать путь поиска, указанный в PATH» и «Некоторые более старые реализации искали файл в текущем каталоге, даже если значение PATH запрещало его».
kmkaplan
1

./cmd использует явный путь ( ./- текущий каталог) к исполняемому файлу. И не обязательно, чтобы это начиналось с #!.

. cmd- (иначе source) - встроенная команда bash. Одно из видимых отличий в выполнении source: он может устанавливать / изменять переменную окружения текущей оболочки.

Леонид Вольницкий
источник
точнее, sourceпсевдоним только для bash .(который является стандартным)
user1686 22.12.12
Вы правы. Исправлена.
Леонид Вольницкий