Como executar o find -exec?


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.


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

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.


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


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

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"

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.