Bash: Citação em substituição de comando

Bash: Citação em substituição de comando

Resumindo, quero usar diretórios listados por um comando em um findcomando:

find $(produces_dir_names --options...) -find-options...

O problema vem com espaços em branco nos nomes dos diretórios. Achei que citá-los na saída do comando de produção (que posso alterar) seria suficiente:

"a" "a b" "a b c"

mas bash reclama:

find: ‘"a"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b’: No such file or directory
find: ‘c"’: No such file or directory

Como você pode ver, bashdividirá a saída do comando em espaços, mesmo com aspas. Tentei mexer IFSe configurá-lo para \n, mas minha compreensão parece muito limitada para fazê-lo funcionar.

A única solução alternativa que encontrei foi nesta pergunta do Stack Overflow: substituição do comando bash remover cotação, ou seja, colocar um evalna frente dele, mas isso parece meio feio.

Minhas perguntas:

Existe uma maneira fácil e como seria escrever essa substituição, sem o eval?

As citações são mesmo necessárias?

Exemplo (produzindo a mesma saída):

find $(echo '"a" "a b" "a b c"')

Responder1

Talvez em duas linhas

IFS=$'\n' DIRS=( $(produces_dir_names --options...) ) 
find "${DIRS[@]}" -find-options...

Exemplo:

$ mkdir -p "/tmp/test/a b/foo" "/tmp/test/x y/bar"

$ IFS=$'\n' DIRS=( $(printf "/tmp/test/a b\n/tmp/test/x y\n") )
$ find "${DIRS[@]}" -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar

Mas em geral este não é um bom estilo. Por exemplo, você terá problemas se o seu DIRS contiver novas linhas. Melhor corrigir seu "produces_dir_names" para imprimir strings terminadas em bytes nulos. Em relação ao meu exemplo, isso seria algo como:

$ printf "/tmp/test/a b\0/tmp/test/x y\0" | xargs -0 -I '{}' find '{}' -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar

Se você não consegue corrigir "produces_dir_names", em relação ao meu último comentário, a solução mais geral seria assim:

produces_dir_names --options... | tr '\n' '\0' | xargs -0  -I '{}' find '{}' -find-options...

Ainda problemas com "novas linhas", a menos que você corrija "produces_dir_names" para evitar arquivos tr.

Responder2

resposta de Rudimeieré bom - especificamente, a parte sobre a modificação produces_dir_names para imprimir strings terminadas em nulo - mas pode não ser óbvio pela resposta que ele é executado finduma vez para cada diretório. Se isso for bom o suficiente, tudo bem. Mas, claro, é possível invocar find com múltiplos pontos de partida; por exemplo,

encontrar  diretório 1 diretório 2 diretório 3  -opções de localização...

e parece que é isso que você quer. Isso pode ser feito da seguinte forma:

printf "a\0a b\0a b c" | xargs -0 sh -c 'encontrar "$@" -opções de localização...'sh

Isso faz com xargsque seja invocado sh -cuma vez, com todos os nomes de diretório anexados ao comando. O shell será então expandido "$@"para uma lista desses nomes de diretório.

PS Se produces_dir_nameslistar muitos nomes de diretório para colocar em uma linha de comando, xargsserá forçado a gerar alguns comandos. Use xargs --verbosepara ver quais comandos xargsestão sendo gerados.

Responder3

Apenas para esclarecer o mistério das mensagens de erro que você está recebendo:

find: ‘"a"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b’: No such file or directory
find: ‘c"’: No such file or directory

A resposta é queA remoção de cotações do Bash não remove aspas queresultouda substituição de comando.

DeLESS='+/^ *Quote Removal' man bash

Quote Removal
    After the preceding expansions, all unquoted occurrences of the charac-
    ters  \,  ', and " that did not result from one of the above expansions
    are removed.

As "expansões anteriores" mencionadas incluem:

EXPANSION
   Brace Expansion
   Tilde Expansion
   Parameter Expansion
   Command Substitution
   Arithmetic Expansion
   Process Substitution
   Word Splitting
   Pathname Expansion
   Quote Removal

informação relacionada