No manual de Bash ( man bash
):
Command Substitution Command substitution allows the output of a command to replace the command name. There are two forms: $(command) or 'command' Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of the command, with any trailing newlines deleted. Embedded newlines are not deleted, but they may be removed during word splitting. The command substitution $(cat file) can be replaced by the equivalent but faster $(< file).
(Isso vale para todos os shells parecidos com Bourne, por exemplo, sh
, ksh
, zsh
, bash
etc., e zsh
também é capaz de capturar dados com caracteres NUL incorporados dessa maneira )
O comando
basedir=$(dirname "$(echo "$0" | sed -e 's,\,/,g')")
atribuirá o nome do diretório onde o script está localizado (enquanto também altera todas as barras invertidas em barras) para a variável basedir
. Quaisquer erros, avisos ou outras mensagens de diagnóstico que são enviados para o fluxo de erro padrão ainda serão exibidos no terminal ( $(...)
captura apenas a saída padrão do comando).
O shell iniciará executando a substituição do comando mais interno:
echo "$0" | sed -e 's,\,/,g'
A saída será dada como uma string para dirname
, e a saída disso será atribuída à variável basedir
.
As aspas duplas existem para garantir que nenhuma divisão de palavras ou globalização de nome de arquivo seja feita; caso contrário, você pode descobrir que o script falha ou produz uma saída estranha quando $0
(o nome do script incluindo o caminho usado para execute it) contém um caractere de espaço ou um caractere globbing de nome de arquivo (como ?
ou *
).
Em geral, é uma boa ideia sempre citar expansões (expansões de variáveis, substituições de comandos e expansões aritméticas). Veja esta pergunta e suas respostas para uma excelente explicação do motivo pelo qual esta é uma boa ideia.
Se o script foi executado como
$ /usr/local/bin/script.sh
, em seguida, basedir
obterá o valor de /usr/local/bin
.
Ou no Cygwin:
$ bash c:\Users\Me\script.sh
, em seguida, basedir
obterá o valor de c:/Users/Me
. As barras invertidas duplas na linha de comando neste caso são apenas para escapar das únicas barras invertidas do shell. O valor real de $0
é c:\Users\Me\script.sh
.
Outra maneira de fazer a mesma coisa sem usar dirname
, echo
e sed
seria
basedir="${0//\//}"
basedir="${basedir%/*}"