find: argumento ausente para -exec

find: argumento ausente para -exec

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 -ocláusulas e diferentes implementações de findused ( 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 - execestá 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 findcompatível com GNU POSIX).

Se você quiser manter uma localização GNU mais antiga, poderá usar -print0with xargs -0para 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 findlinha de comando. Caso contrário, se você executar este comando a partir de um diretório contendo .carquivos, o valor sem aspas *.cserá expandido para a lista de .carquivos no diretório atual.

Adicionar /dev/nullà greplinha de comando é um truque para garantir que o grep sempre imprima o nome do arquivo, mesmo que findencontre 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 findque não suporta sintaxe -exec mycommand {} +. Nesse caso, a substituição de baixo desempenho deve ser executada, -exec mycommand {} \;o que executará mycommanduma vez para cada destino encontrado, em vez de coletar vários destinos e executar mycommandapenas uma vez.

No entanto, o GNU findnão suporta, por exemplo

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +

porque o GNU findsuporta 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, findprecisará 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 -csinalizador.

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

informação relacionada