Chamando um script com ./bla.sh vs. bla.sh

11

Alguém pode me explicar o que o shell faz nos dois exemplos A) e B) abaixo? Obviamente, ele se comporta de maneira diferente, mas não consigo descobrir por que a saída é diferente.

Exemplo:
Vamos ter um script em nosso diretório atual nomeado bla.shcom apenas um comando:
echo ${0##/*} hello

A)
Começou como: ./bla.sh
dá:./bla.sh hello

B)
Iniciado como: . bla.sh
dá:-bash hello

Como eu uso isso em um script, a segunda saída (por causa do "-" na frente do -bash) mata o comando. Claro, um simples --antes do ${...}ajudou, mas eu adoraria entender o que causa a saída em primeiro lugar.
Eu amo bash. E vi [m]. Mas eu discordo ...

Lobo
fonte

Respostas:

22
./bla.sh

Aqui, o comando é ./bla.sh. Isso faz com que o shell procure um executável nomeado bla.shno diretório atual e peça ao kernel para executá-lo como um programa normal, em um processo separado do shell. (Não importa se bla.shé um bashscript, um perlou pythonum, ou um binário compilado.)


. bla.sh

Aqui, o comando é .(aka source), um comando interno do seu shell. Faz com que o shell procure um arquivo nomeado bla.shno caminho do sistema ($ PATH) e interprete o conteúdo como se tivesse sido digitado por você; tudo isso é feito no mesmo processo que o próprio shell (e, portanto, pode afetar o estado interno do shell).

Obviamente, isso só funciona quando bla.shcontém comandos para o bashshell (se é o que você está usando no momento), não funcionará para perlscripts ou qualquer outra coisa.

(Isto é explicado em help .e help sourcetambém.)


Como .e ./são coisas completamente diferentes (um comando versus parte de um caminho), elas podem ser combinadas, é claro - usando . ./bla.sh"originaria" um arquivo bla.shno diretório atual.


Geralmente é melhor usar o ./bla.shmétodo Apenas ~/.bashrc, ~/.profilee esses arquivos são geralmente de origem, porque eles são supostamente para modificar o ambiente atual.

user1686
fonte
3
Além disso, se você alterar o ambiente do bash no bla.sh, essas alterações serão levadas em consideração depois. bla.sh, mas não depois de ./bla.sh. isto é porque . O bla.sh é executado no contexto do bash atual, enquanto o ./bla.sh é executado como um subprocesso.
Mouviciel 15/09/09
1
Veja também mywiki.wooledge.org/BashFAQ/060 para alguns exemplos. Observe que sourceé um alias do bash para ., não o contrário e sourcenão funcionará em outros shells.
Mrucci #
7

./<cmd>executará o <cmd>programa que reside no diretório atual em um novo processo (bifurcado). Tem que ser executável. E também legível começa com #!.

. <cmd>fará com que seu shell atual execute o script do shell <cmd>que reside no seu $PATHdiretório ou no atual no processo atual do shell. Tem que ser legível. É um alias para o comando shell source.

kmkaplan
fonte
-1 . <cmd>procurará o programa $PATHe, se não for encontrado, procurará o diretório atual.
dogbane
@dogbane Certo, eu corrigi isso.
kmkaplan
FWIW, nem todos os shells procurarão no cwd por sripts de origem. zsh (pelo menos com a configuração tenho) exige. ./cmd
bstpierre
1
@bstpierre Este parece ser um terreno em movimento. A referência POSIX que eu disse diz que "o shell deve usar o caminho de pesquisa especificado por PATH" e "Algumas implementações mais antigas pesquisaram o arquivo atual no diretório atual, mesmo que o valor de PATH não o permitisse".
Kmkaplan 21/12/12
1

./cmd usa caminho explícito ( ./- dir atual) para executável. E não é necessário que comece com #!.

. cmd- (aka source) - comando bash builtin. Uma diferença visível da execução sourceé que ele pode definir / modificar a variável de ambiente do shell atual.

Leonid Volnitsky
fonte
mais precisamente, sourceé um nome alternativo só de festa para .(que é o padrão)
user1686
Você está certo. Fixo.
Leonid Volnitsky