Estou tentando executar o seguinte comando:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +
Isso está retornando um erro:
find: missing argument to -exec
Não consigo ver o que há de errado com este comando, pois parece corresponder à página de manual:
-exec comando {} +
Esta variante da opção -exec executa o comando especificado nos arquivos selecionados, mas a linha de comando é construída anexando cada nome de arquivo selecionado no final; o número total de invocações do comando será muito menor que o número de arquivos correspondentes. A linha de comando é construída da mesma maneira que o xargs constrói suas linhas de comando. Apenas uma instância de '{}' é permitida no comando. O comando é executado no diretório inicial.
Eu também tentei:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' '{}' +
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar '{}' +
find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar '{}' +
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
Responder1
Houve vários problemas com suas tentativas, incluindo crases usados em vez de aspas (removidos em edições posteriores da pergunta), aspas ausentes onde são necessárias, aspas extras onde são inúteis, parênteses ausentes para agrupar -o
cláusulas e diferentes implementações de find
used ( veja os comentários e chat para detalhes).
De qualquer forma, o comando pode ser simplificado assim:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +
ou, se você usar uma versão arcaica do GNU find, isso sempre funcionará:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
Responder2
“faltando argumento para -exec
” geralmente significa que o argumento para - exec
está faltando seu terminador. O terminador deve ser um argumento contendo apenas o caractere ;
(que precisa ser citado em um comando shell, por isso é normalmente escrito \;
ou ';'
) ou dois argumentos sucessivos contendo {}
e +
.
Stéphane Chazelas identificouque você está usando uma versão mais antiga do GNU find que não suporta -exec … {} +
apenas -exec {} \;
. Embora o GNU tenha adotado tardiamente o -exec … {} +
, eu recomendo que você obtenha um conjunto de ferramentas menos antigo (comoCygwin, que inclui git e muito mais, ouGNUwin32, que não possui git, mas não tem a vibração de mau funcionário tentando usar o Linux, mas impomos o Windows que o Cygwin oferece). Este recurso foi adicionado na versão 4.2.12, há mais de 9 anos (foi o último recurso identificado para tornar find
compatível com GNU POSIX).
Se você quiser manter uma localização GNU mais antiga, poderá usar -print0
with xargs -0
para obter uma funcionalidade semelhante: execução de comandos agrupados, suportando nomes de arquivos arbitrários.
find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null
Sempre cite os curingas na find
linha de comando. Caso contrário, se você executar este comando a partir de um diretório contendo .c
arquivos, o valor sem aspas *.c
será expandido para a lista de .c
arquivos no diretório atual.
Adicionar /dev/null
à grep
linha de comando é um truque para garantir que o grep sempre imprima o nome do arquivo, mesmo que find
encontre uma única correspondência. Com o GNU find, outro método é passar a opção -H
.
Responder3
Se um comando como
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
retorna erro
find: missing argument to -exec
a causa provável é um GNU muito antigo find
que não suporta sintaxe -exec mycommand {} +
. Nesse caso, a substituição de baixo desempenho deve ser executada, -exec mycommand {} \;
o que executará mycommand
uma vez para cada destino encontrado, em vez de coletar vários destinos e executar mycommand
apenas uma vez.
No entanto, o GNU find
não suporta, por exemplo
find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
porque o GNU find
suporta apenas combinações literais {} +
em vez de combinações mais genéricas {} additional parameters +
. Observe que não pode haver nada entre os colchetes e o +
caractere. Se você tentar isso, receberá o mesmo erro:
find: missing argument to -exec
A solução alternativa é usar uma sintaxe {} additional parameters \;
que funcione, mas executará o comando uma vez para cada destino encontrado. Se você precisar de mais desempenho com o GNU, find
precisará escrever um script wrapper que possa acrescentar parâmetros adicionais aos argumentos fornecidos. Algo como
#!/bin/bash
exec mycommand "$@" additional parameters
deve ser bom o suficiente. Ou, se não quiser criar um arquivo temporário, você pode usar uma linha para alterar a ordem dos parâmetros como este:
find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +
que será executado mycommand {list of ttf files} extra arguments
. Observe que você pode precisar de caracteres especiais de escape duplo para o bash após o -c
sinalizador.
Responder4
Eu tive muitas dores de cabeça com a sintaxe exec no passado. na maioria dos dias eu prefiro a sintaxe bash mais agradável:
for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done
Ele tem algumas limitações quando você deseja tratar os arquivos como um grupo, já que cada um é avaliado em série, mas você pode canalizar a saída para outro lugar perfeitamente