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 do manual :

Comando -exec {} +

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 do que o número de arquivos correspondentes. A linha de comando é construída da mesma maneira que xargs constrói seu linhas de comando. Apenas uma instância de “{}” é permitida dentro do 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 "{}" \+ 

Comentários

  • Você já tentou escapar de + no final? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
  • Você pode estar usando uma versão antiga do GNU find. Embora a -exec cmd {} + variante seja POSIX e esteja disponível desde os anos 80, o GNU find apenas a adicionou (relativamente) recentemente (2005). O que find --version diz a você?
  • @Koveras, seria isso então. -exec {} + foi adicionado em 4.2.12 em 2005. Em achados GNU mais antigos, você pode usar o -print0 | xargs -r0 (não POSIX) para obter algo semelhante. 4.1 é de 1994.
  • JRFerguson apontou (em uma resposta que foi excluída) que o padrão -name os argumentos devem ser citados: -name "*.c" -o -name "*.h". Isso é verdade, embora não esteja relacionado ao erro -exec. Você notará que todas as outras respostas colocam os curingas entre aspas, embora apenas Gilles mencione isso. … (Continuação)
  • (Continuação)… a resposta de jlliagre reduz a expressão do nome para -name "*.[ch]" sem explicação. Isso tem os benefícios de simplificar a linha de comando e, especificamente, eliminar o -o. Encontre expressões que envolvam -o são difíceis de obter. O seu está errado; se o seu comando for corrigido de forma que não falhe (como na resposta de Gilles), ele será executado grep apenas no .h arquivos. Você precisa fazer '(' -name '*.c' -o -name '*.h' ')'.

Resposta

Havia 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 o grupo -o cláusulas e diferentes implementações de find usadas (consulte os comentários e o bate-papo para obter 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 GNU find arcaica, isso sempre deve funcionar:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \; 

Comentários

  • Ops, eles deveriam ser citações, não crases.
  • As citações seriam inúteis, pois {} não tem um significado específico para o shell.
  • Nas páginas do manual de localização: ” A string ‘ { } ‘ é substituído pelo nome do arquivo atual sendo processado em todos os lugares em que ocorre nos argumentos do comando, não apenas nos argumentos onde está sozinho, como em algumas versões de find. Ambas as construções podem precisar de escape (com um ‘ \ ‘) ou citadas para protegê-las da expansão pelo shell. ”
  • Eu realmente li isso na página de manual, mas o fato é que não há shell que ‘ estou ciente de isso requer a citação das chaves. Qual shell você está usando?
  • bash. Com ou sem as aspas, recebo o erro de qualquer maneira.

Resposta

“argumento ausente 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, portanto “é normalmente escrito \; ou ";"), ou dois argumentos sucessivos contendo {} e +.

Stephane Chazelas identificou que você está usando uma versão mais antiga do GNU find que não é compatível com -exec … {} +, apenas -exec {} \;.Embora GNU tenha adotado tardiamente o -exec … {} +, recomendo que você obtenha um conjunto de ferramentas menos antigo (como o Cygwin , que inclui git e muito mais, ou GNUwin32 , que não tem git, mas não tem o mau-funcionário-tentando-usar-linux -but-we-impe-windows vibe que Cygwin oferece). Este recurso foi adicionado na versão 4.2.12, há mais de 9 anos (foi o último recurso identificado para tornar o GNU find Compatível com POSIX).

Se você deseja manter um achado GNU mais antigo, pode usar -print0 com xargs -0 para obter uma funcionalidade semelhante: execução de comandos agrupados, com suporte a 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 no find linha de comando. Caso contrário, se você executar este comando de um diretório contendo .c arquivos, o *.c não citado será d ser expandido para a lista de .c arquivos no diretório atual.

Adicionando /dev/null ao grep a linha de comando é um truque para garantir que grep sempre imprimirá o nome do arquivo, mesmo se find encontrar uma única correspondência. Com GNU find, outro método é passar a opção -H.

Comentários

  • O que você quer dizer por mau funcionário-tentando-usar-linux-mas-nós-impomos-windows a vibração que o cygwin dá?
  • GNUwin32 não ‘ espera 🙁
  • Veja meu (s) comentário (s) sobre a questão.
  • As citações em torno do seminário funcionaram em um script package.json.

Resposta

Se um comando como

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} + 

retornar erro

find: missing argument to -exec 

a causa provável é GNU muito antigo find que não suporta sintaxe -exec mycommand {} +. Nesse caso, a substituição de baixo desempenho é executar -exec mycommand {} \; que executará mycommand uma vez para cada alvo encontrado em vez de coletar vários alvos e executando o mycommand apenas uma vez.

No entanto, GNU find precisa s não é compatível, por exemplo,

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

porque GNU find oferece suporte apenas à combinação literal {} + em vez de mais genérico {} additional parameters +. Observe que não pode haver nada entre as chaves e o caractere +. Se você tentar isso, obterá o mesmo erro:

find: missing argument to -exec 

A solução alternativa é usar a sintaxe {} additional parameters \; que funciona, mas executará o comando uma vez para cada alvo encontrado. Se você precisa de mais desempenho com GNU find, você deve escrever um script de wrapper que pode anexar 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 executará mycommand {list of ttf files} extra arguments. Observe que você pode precisar fazer o escape duplo de caracteres especiais para o bash após o sinalizador -c.

Comentários

  • (1) A parte do acima que realmente responde à pergunta já foi dada por outras pessoas. (2) O que você está descrevendo não é uma falha ou deficiência no GNU find, mas o comportamento correto especificado pelo POSIX .
  • +1 Finalmente, alguém que responde por que parâmetros adicionais não ‘ funcionam! Parece uma deficiência na definição POSIX.
  • Se você ‘ ve GNU find você ‘ provavelmente temos GNU cp. Nesse caso, você pode find ... -exec cp --target-directory ~/.fonts {} + para manter o {} no final da string de execução.

Resposta

find . -type f -perm 0777 -exec chmod 644 {}\;

erro obtido find: missing argument to ``-exec".

Adicionar espaço entre {} e \ corrigiu o problema:

find . -type f -perm 0777 -print -exec chmod 644 {} \;

Comentários

  • Esse problema não existe no find na questão em questão.
  • Na questão não é, tudo bem, que eu entendi, mas o problema é o mesmo ” find: missing argument para “ -exec ‘ “, O problema pode ocorrer por motivo diferente-2, respondi porque vi a mesma declaração de problema.
  • @Kusalananda good grief, o noob forneceu uma solução para o erro relatado que é declarado pelo OP no título e no corpo da pergunta.
  • @bvj A pergunta trata explicitamente com a + forma da opção -exec para find. Esta resposta está corrigindo um problema que o usuário que fez a pergunta não tem.

Resposta

Eu tive meu compartilhamento de dores de cabeça com a sintaxe exec no passado. na maioria dos dias agora eu prefiro a sintaxe bash mais agradável:

for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done 

Ela 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 sem problemas

Comentários

  • Embora isso tenda a funcionar, é significativamente menos útil do que a versão pure-find porque não pode lidar com arquivos com espaço em branco no nome corretamente.
  • Não, ‘ não faça isso. Isso quebra assim que os arquivos contêm espaços e outros caracteres “estranhos”. Isso também é mais complexo e mais lento do que find … -exec … \;, então ‘ não há razão para usar isso, mesmo se você souber que os nomes dos seus arquivos são domesticado.
  • isso foi útil para a minha situação onde eu precisava executar várias linhas de lógica com base nos nomes dos arquivos (como remover chars, criar diretórios e mover os arquivos). Tentar encontrar para fazer várias coisas em um exec era uma grande dor de cabeça para os 5 minutos que eu queria gastar nisso. Meus nomes de arquivo eram inofensivos e isso resolveu meu problema 🙂

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *