Bash - A substituição de comandos adiciona aspas simples

2

Eu tenho um problema com o comportamento bash ao avaliar sotaques graves. Eu quero correr encontrar com o nome opcional:

find -name "*.log"

funciona bem, mas quando eu quero pegar a parte -name do script aninhado

find 'echo "-name \"*.log\""'

simplesmente não funciona. Executando-o sob bash -x mostra que este comando é avaliado para

find -name '"*.log"'

Aparentemente, é por causa dessas citações simples. Existe alguma solução para se livrar deles? Atenciosamente.

// SO solicitado e versão do bash: Debian, 7,8 wheezy, Bash 4.2.37 (1) -release

    
por tm852 11.04.2015 / 14:45

1 resposta

1

O Bash não adicionou aspas simples ao comando. As aspas simples que você vê são adicionadas para que o comando exibido seja uma sintaxe bash válida. Se você ver

find -name '"*.log"'

significa que o bash foi instruído a executar este comando: find com dois argumentos -name e "*.log" (as aspas duplas fazem parte do argumento). Poderia ter sido inserido exatamente assim ou de alguma outra forma equivalente como

find -name \"*.log\"
find -name "\"*.log\""
find -name '"*.'log""\"

Agora vamos ver o que você escreveu:

find 'echo "-name \"*.log\""'

O comando em execução na subshell é

echo "-name \"*.log\""

Sua saída é

-name "*.log"

É daí que vêm as aspas duplas no argumento. Quando a saída de uma substituição de comando é interpolada em uma linha de comando, ela não é analisada como sintaxe do shell - assim, por exemplo

find 'echo '; rm -rf ~''

não excluirá todos os seus arquivos, mas transmitirá ; como o primeiro argumento para find , rm como o segundo, -rf como o terceiro e seu diretório inicial (supondo que ele não contenha nenhum especial caracteres) como o quarto.

Quando uma substituição de variável ou uma substituição de comando está fora de aspas duplas, as seguintes transformações ocorrem no valor da variável ou na saída do comando:

  1. Apenas para substituição de comandos: novas linhas finais são removidas.
  2. A string é dividida em partes delimitadas por espaços em branco. (Você pode configurar os delimitadores definindo a variável IFS .) Observe que o resultado dessa transformação é uma lista de strings.
  3. Cada elemento da lista é interpretado como um padrão de caractere curinga. Se esse padrão corresponder aos arquivos, o elemento será substituído pela lista de arquivos correspondentes (isso é chamado de globbing ) . Se o padrão não corresponder a nenhum arquivo, o elemento será deixado sozinho.

A etapa 2 divide a string -name "*.log" em duas partes: -name e "*.log" . Nenhuma das partes corresponde a nenhum arquivo, portanto, o resultado são as duas palavras -name e "*.log" .

O que você pretendia fazer é executar find com os argumentos -name e *.log . Você pode fazer isso desligando globbing:

set -f
find 'echo -name *.log'
set +f

Isso não é robusto: não permitirá que você passe nomes de arquivos contendo espaço em branco, por exemplo. De um modo geral, você não deve tentar criar comandos armazenando bits deles em uma variável ou passando-os em comandos. A melhor maneira de fazer o que você está fazendo depende do que você está realmente tentando fazer. Aqui estão alguns conselhos gerais:

por 12.04.2015 / 03:02