Resposta curta
Na sua pergunta, o segundo comando não usa nem o .
shell interno nem o source
interno. Em vez disso, você está realmente executando o script em um shell separado, invocando-o pelo nome, como faria com qualquer outro arquivo executável. Isso fornece a ele um conjunto separado de variáveis (embora, se você exportar uma variável em seu shell pai, ela será uma variável de ambiente para qualquer processo filho e, portanto , será incluída nas variáveis de um shell filho ). Se você alterar /
para um espaço, isso o executaria com o .
built-in, que é equivalente a source
.
Explicação estendida
Esta é a sintaxe do source
shell interno, que executa o conteúdo de um script no shell atual (e, portanto, com as variáveis do shell atual):
source testenv.sh
Esta é a sintaxe do .
built-in, que faz o mesmo que source
:
. testenv.sh
No entanto, essa sintaxe executa o script como um arquivo executável, iniciando um novo shell para executá-lo:
./testenv.sh
Isso não está usando o .
built-in. Em vez disso, .
faz parte do caminho para o arquivo que você está executando. De um modo geral, você pode executar qualquer arquivo executável em um shell, invocando-o com um nome que contenha pelo menos um /
caractere. Executar um arquivo no diretório atual, precedê-lo ./
é, portanto, a maneira mais fácil. A menos que o diretório atual está na sua PATH
, você não pode executar o script com o comando testenv.sh
. Isso evita que as pessoas executem acidentalmente arquivos no diretório atual quando pretendem executar um comando do sistema ou algum outro arquivo existente em algum diretório listado na PATH
variável de ambiente.
Como a execução de um arquivo pelo nome (em vez de com source
ou .
) o executa em um novo shell, ele terá seu próprio conjunto de variáveis de shell. O novo shell herda as variáveis de ambiente do processo de chamada (que neste caso é o seu shell interativo) e essas variáveis de ambiente se tornam variáveis do shell no novo shell. No entanto, para que uma variável do shell seja passada para o novo shell, um dos seguintes deve ser o caso:
A variável shell foi exportada, fazendo com que ela seja uma variável de ambiente. Use o export
shell interno para isso. No seu exemplo, você pode usar export MY_VAR=12345
para definir e exportar a variável em uma etapa ou, se já estiver definida, pode simplesmente usar export MY_VAR
.
A variável shell é explicitamente configurada e transmitida para o comando que você está executando, fazendo com que seja uma variável de ambiente pela duração do comando que está sendo executado. Isso geralmente faz com que:
MY_VAR=12345 ./testenv.sh
Se MY_VAR
é uma variável do shell que não foi exportada, você pode até executar testenv.sh
com MY_VAR
passado como uma variável de ambiente configurando-a para si mesma :
MY_VAR="$MY_VAR" ./testenv.sh
./
Sintaxe para scripts requer uma linha Hashbang para funcionar (corretamente)
A propósito, observe que, quando você invoca um executável por nome, como acima (e não com os built-ins .
ou ou source
shell), qual programa shell é usado para executá-lo geralmente não é determinado por qual shell você o está executando. . Em vez de:
Para arquivos binários, o kernel pode ser configurado para executar arquivos desse tipo específico. Ele examina os dois primeiros bytes do arquivo em busca de um "número mágico" que indica que tipo de executável binário é. É assim que os binários executáveis são capazes de executar.
Isso é, obviamente, extremamente importante, porque um script não pode ser executado sem um shell ou outro intérprete, que é um binário executável! Além disso, muitos comandos e aplicativos são binários compilados em vez de scripts.
( #!
é a representação em texto do "número mágico" indicando um texto executável.)
Para arquivos que devem ser executados em um shell ou em outra linguagem interpretada, a primeira linha se parece com:
#!/bin/sh
/bin/sh
pode ser substituído por qualquer outro shell ou intérprete destinado a executar o programa. Por exemplo, um programa Python pode começar com a linha:
#!/usr/bin/python
Essas linhas são chamadas hashbang, shebang e vários outros nomes semelhantes. Veja esta entrada do FOLDOC , este artigo da Wikipedia e #! / Bin / sh é lida pelo intérprete? Para maiores informações.
Se um arquivo de texto estiver marcado como executável e você o executar a partir do seu shell (como ./filename
), mas não começar #!
, o kernel falhará ao executá-lo. No entanto, vendo que isso aconteceu, seu shell tentará executá-lo passando seu nome para algum shell. Existem poucos requisitos sobre o que é o shell ( "o shell deve executar um comando equivalente a ter um shell invocado ..." ). Na prática , algumas conchas - incluindo bash
* - executam outra instância de si mesmas, enquanto outras usam/bin/sh
. Eu recomendo que você evite isso e use uma linha hashbang (ou execute o script passando-o para o intérprete desejado, por exemplo, bash filename
).
* Manual do GNU Bash , 3.7.2 Pesquisa e Execução de Comandos : "Se esta execução falhar porque o arquivo não está no formato executável e o arquivo não é um diretório, é considerado um shell script e o shell o executa como descrito em scripts de shell ".
source
é que as funções se tornaram disponíveis no bash sem a necessidade de carregar ou iniciar novamente. Exemplo#!/bin/bash function olakease {echo olakease;}
. Depois de carregá-lo,source file.sh
você pode ligar diretamenteolakease
do bash. Eu realmente gosto daquilo. Fonte executa então cargas monte de coisas, o ponto.
é apenas para execução e é algo como o usobash file.sh