Está na hora de resolver esse enigma que me incomoda há anos ...
Venho encontrando isso de vez em quando e pensei que este é o caminho a seguir:
$(comm "$(arg)")
E pensei que minha visão era fortemente apoiada pela experiência. Mas não tenho mais tanta certeza. O Shellcheck também não consegue se decidir. São os dois:
"$(dirname $0)"/stop.bash
^-- SC2086: Double quote to prevent globbing and word splitting.
E:
$(dirname "$0")/stop.bash
^-- SC2046: Quote this to prevent word splitting.
Qual é a lógica por trás?
(É o Shellcheck versão 0.4.4, btw.)
bash
quoting
command-substitution
Tomasz
fonte
fonte
"$(dirname "$0")"/stop.bash
:? Parece funcionar ... Qual é a história?shell_level_1 $(shell_level_2) shell_level_1
quando você está dentro do,$(....)
insere um "subnível" do shell, MAS você pode escrever nele como se estivesse no nível primário (ou seja, você pode escrever diretamente em"
vez de\"
etc). ex:touch "/tmp/a file" ; echo "its size is: $(find "/tmp/a file" -ls | awk '{print $5}) ..." : if you used backticks you'd have to
encontre \ "/ tmp / um arquivo \" `eprint \$5
. Sem$(...)
necessidade: o shell se adapta ao novo nível e você pode escrever diretamente como se o seu intérprete agora estivesse nesse nível também.Respostas:
Você precisa usar
"$(somecmd "$file")"
.Sem as aspas, um caminho com um espaço será dividido no argumento para
somecmd
e direcionará o arquivo errado. Então você precisa de aspas no interior.Quaisquer espaços na saída de
somecmd
também causarão divisão, portanto, você precisa de aspas na parte externa de toda a substituição do comando.As aspas dentro da substituição de comando não têm efeito nas aspas fora dela. O manual de referência do Bash não é muito claro, mas o BashGuide menciona explicitamente . O texto no POSIX também exige isso, pois "qualquer script de shell válido" é permitido dentro
$(...)
:Exemplo:
uma. Sem aspas,
dirname
processa ambos./space
ehere/foo
:b. Citações dentro,
dirname
processos./space here/foo
, doações./space here
, que são divididas em duas:c. As aspas externas,
dirname
processam ambos./space
ehere/foo
, são exibidas em linhas separadas, mas agora as duas linhas formam um único argumento :d. Cita dentro e fora, isso fornece a resposta correta:
(isso possivelmente seria mais simples se
dirname
apenas processasse o primeiro argumento, mas isso não mostraria a diferença entre os casos a e c.)Observe que com
dirname
(e possivelmente outros) você também precisa adicionar--
, para impedir que o nome do arquivo seja usado como uma opção, caso ele comece com um traço, use-o"$(dirname -- "$file")"
.fonte
$( )
cria um novo contexto; portanto, as aspas dentro dele são independentes das aspas fora dele. E você geralmente deseja aspas nos dois contextos.