Como executar o find -exec?

477

Eu gostaria de encontrar os arquivos no diretório atual que contêm o texto "chrome".

$ find . -exec grep chrome
find: missing argument to `-exec'

O que estou fazendo errado?

ripper234
fonte
Eu conseguifind: Only one instance of {} is supported with -exec ... +
Costa
2
Related: Como usar -execcomfind
Kusalananda

Respostas:

710

Você perdeu um ;(escapou aqui \;para impedir que o shell o interprete) ou um +e um {}:

find . -exec grep chrome {} \;

ou

find . -exec grep chrome {} +

findserá executado grepe substituirá {}pelos nomes de arquivo encontrados. A diferença entre ;e +é que, com ;um único grepcomando para cada arquivo, é executado, enquanto o +maior número possível de arquivos é fornecido como parâmetro de grepuma só vez.

bmk
fonte
30
Se você usar o \; a construção final grep é passada um arquivo de cada vez; portanto, não exibe o nome do arquivo por padrão, apenas as linhas correspondentes. Para obter uma lista de arquivos, adicione o uso grep -lsdentro da construção find.
Caleb
9
find . -exec grep foo {} +mostrará uma saída como esta./dir/file.py:from foo import bar
sg
10
find . -exec grep foo {} \;mostrará a você a saída como estafrom foo import bar
sg
9
find . -exec grep -l foo {} +mostrará a você a saída como esta./dir/file.py
sg
8
find . -exec grep -l foo {} \;mostrará a você a saída como esta./dir/file.py
sg
46

Você não precisa usar findpara isso; O grep é capaz de lidar com a abertura dos arquivos a partir de uma lista global de tudo no diretório atual:

grep chrome *

... ou até recursivamente para a pasta e tudo sob ela:

grep chrome . -R
Caleb
fonte
22
O grep engasgará se a expansão ultrapassar ARG_MAX. O -R visitará tudo enquanto estiver usando o find, é possível adicionar primitivos com mais facilidade para excluir determinados arquivos (-name, etc) ou nem mesmo visitar as subárvores (-une).
Mel
6
Bons pontos @Mel. Meu argumento era que, com toda a probabilidade, a parte solicitante estava tornando as coisas mais complexas do que o necessário, apresentando findquando greppoderia fazer o trabalho, mas, em alguns casos, seria mais eficaz usar o find para refinar a lista de arquivos antes de sair para grep.
Caleb
4
@Mel grepnão engasga nesse caso, execfaz.
26413 Chris Down
Funciona apenas no caso de todos os arquivos estarem no mesmo diretório, não quando estão espalhados por subdiretórios.
Yaba
1
@Yaba Minha resposta indica como lidar com o caso de arquivos espalhados por subdiretórios.
Caleb
18
find . | xargs grep 'chrome'

você também pode fazer:

find . | xargs grep 'chrome' -ls

O primeiro mostra as linhas nos arquivos, o segundo apenas lista os arquivos.

A opção de Caleb é mais limpa, menos pressionamentos de tecla.

Mathew
fonte
11
O problema xargsé que ele espera que sua entrada seja citada de uma maneira peculiar que findnão produza. Portanto find … | xargs …, não funciona se você tiver nomes de arquivos que contenham espaços em branco ou \'".
Gilles
3
@ Gilles Você pode contornar esse problema usando algo como, find . | xargs -n1 -iX grep "X" 'chrome'para que os argumentos sejam alimentados um de cada vez e citados. Obviamente, essa é uma maneira terrivelmente ineficiente de lidar com este exemplo, mas para algumas situações é bom.
Caleb
Para completar, também devemos mencionar a opção -i para insensibilidade a maiúsculas e minúsculas com 'grep'. Também existe -iname em busca de insensibilidade ao caso.
Mathew
9
@ Caleb: A única maneira 100% confiável de xargslidar com os nomes de arquivos do Linux é find ... -print0 | xargs -0usando NUL como separador. Alternativa - xargs -d '\n'usando nova linha como separador, 99% de confiabilidade.
grawity
Eu uso isso frequentemente, mas falhará em listas muito longas de nomes de arquivos; nesse momento, find -exec se torna o vencedor.
Spacemoose
5

Encontrar é uma maneira e você pode tentar. the_silver_searcherTudo o que você precisa fazer é

ag chrome

Ele pesquisará o chrome em todos os arquivos (incluindo subdiretórios) e é mais rápido do que o encontrado

Peça e aprenda
fonte
Há também pt (pesquisador de platina, disponível em github.com/monochromegane/the_platinum_searcher ) que, IMHO, faz o trabalho mais rapidamente - pode não importar se houver apenas alguns arquivos.
Hopping Coelho
1

Para ver a lista de arquivos em vez de linhas:

grep -l "chrome" *

ou:

grep -r -l "chrome" .
mateusz.szymborski
fonte
1

Aqui está um exemplo de como eu costumo usar find / exec ...

find  . -name "*.py" -print -exec fgrep hello {} \;

Ele procura recursivamente todos os arquivos .py e cada arquivo imprime o nome do arquivo e o fgrep para 'olá' nesse arquivo (para cada). Saída parece (apenas executou uma hoje):

./r1.py
./cgi-bin/tst1.py
print "hello"
./app/__init__.py
./app/views.py
./app/flask1.py
./run.py
./tst2.py
print "hello again"
Jon
fonte
1
não mexer com o seu fluxo de trabalho, mas você pode gostar: find . -name "*.py" -exec fgrep -l hello {} \; - que vai imprimir os nomes de arquivos que correspondem, e nada mais
Jeff Schaller