Diferença entre “. myscript ”e“ ./myscript ”[duplicado]

20

Estou confuso com "apenas um ponto - espaço - shell script nome" (como . myshellscript ) e "caminho para shell script" (como ./myshellscript ) comandos.

O que eles são? Notei que o comando . myshellscript executa o shell script mesmo com -rw-rw-r--. Mas ./myshellscript não. Então estou confuso.

    
por YarLinux 21.02.2013 / 15:05

5 respostas

8

Outros disseram que a diferença é sourcing x executar, mas ninguém descreveu as diferenças funcionais .

A maior diferença funcional é que exit , cd e atribuições de variáveis afetarão o shell atualmente em execução se você o fornecer, mas não se você executá-lo. Para demonstrar, tente o seguinte:

$ cat test.sh
#!/bin/bash

mkdir -p test
cd test
pwd

foo=bar
echo script foo: $foo

$ ./test.sh
/Users/kevin/test
script foo: bar
$ echo $foo

$ pwd
/Users/kevin
$ . test.sh
/Users/kevin/test
script foo: bar
$ echo $foo
bar
$ pwd
/Users/kevin/test
$ 

Agora tente isto:

$ cat test.sh
#!/bin/bash
exit
$ ./test.sh
$ . test.sh

[Process completed]

Como você pode ver, exit em um script executado terminará esse script, mas se você criar um script com exit , ele sairá do seu shell atual!

    
por 21.02.2013 / 16:13
20

help source diz:

source: source filename [arguments]
    Execute commands from a file in the current shell.

    Read and execute commands from FILENAME in the current shell.  The
    entries in $PATH are used to find the directory containing FILENAME.
    If any ARGUMENTS are supplied, they become the positional parameters
    when FILENAME is executed.

    Exit Status:
    Returns the status of the last command executed in FILENAME; fails if
    FILENAME cannot be read.

source é sinônimo de . , o que significa que você pode escrever os dois

. myshellscript

ou

source myshellscript

O que eles fazem: source lê cada linha do arquivo (linha por linha) e o executa no shell atual.

Mas ./myshellscript executa o arquivo no diretório atual se ele tiver os direitos para fazer isso. Isso também poderia ser

/tmp/foo/bar/myshellscript

(para executar o arquivo myshellscript que está no diretório /tmp/foo/bar ) ou

/usr/local/bin/myshellscript

Isso significa que aqui o ponto é apenas o diretório atual . Portanto, ./myshellscript executa o arquivo chamado myshellscript no diretório atual.

Por exemplo, tente

cd .

que muda para o diretório atual (sem alteração real ;-)) ou

ls .

que lista o conteúdo do diretório atual.

E como @Alvin Wong comentou: Você pode experimentar este script

#!/bin/foobarNonExisting

echo "This is the Shell that executes me:"
echo $SHELL

com . ou source para ver que ele não lê a shebang. Apenas usa seu shell atual. Executar o script em si levaria a um erro.

    
por 21.02.2013 / 15:20
9

No bash, . e source funcionalmente executam o mesmo trabalho - executando um script dentro do shell atual.

./foo é executado dentro de outro shell, já que seu shell se bifurca antes da execução.

Se o seu script for portável, use sempre . . source é um sinônimo bash, mas não existe no POSIX.

    
por 21.02.2013 / 15:21
2

. é um sinônimo para o comando source . Em vez de forçar um sub shell para executar o script, ele lê o script no ambiente atual do shell. Em outras palavras, ./script executará o script em uma sub shell criada e fará o processamento ali. Onde . script lê o script no seu shell atual, onde o seu shell atual irá processar os comandos.

Eles fazem o mesmo. Com . script você está lendo e ./script você está executando (gerando um sub-shell) para que as permissões apropriadas sejam necessárias para fazer isso.

    
por 21.02.2013 / 15:16
2

Existem muitas respostas que explicam que . ~/bin/script.sh é equivalente a source ~/bin/script.sh . Aqui está a explicação de por que .

Eu tenho vários clusters que uso para testes e uso variáveis de ambiente para apontar para eles. Normalmente, quando você executa um script, qualquer variável definida nele permanece no escopo desse script. No exemplo:

$ echo $MYFIELD #Nothing set

$ cat test.sh
export MYFIELD=foo #This would set it
$ ./test.sh
$ echo $MYFIELD #Didn't work because the script didn't carry it back to its parent

$ . ./test.sh
$ echo $MYFIELD #When run as a sourced script, this stayed in the context of my current shell
foo

Dessa forma, posso digitar . ~/env/cluster7 e, em seguida, executar qualquer comando que desejar nesse cluster e, em seguida, digitar . ~/env/cluster3 para alterar todas as variáveis de ambiente para apontar para outro sem precisar defini-las manualmente.

Observe que "." no início de uma linha seguida por um espaço é interpretado como um comando. Está tudo bem porque você nunca executaria o único arquivo que pode ser nomeado assim: o diretório atual. Em qualquer outro contexto, por exemplo, sem um espaço a seguir ou em qualquer ponto posterior na linha de comando, ele se refere ao caminho, portanto, . ./test.sh . Como é considerado um comando pelo bash, . test.sh também funciona.

    
por 21.02.2013 / 22:17