Como posso grep os resultados do FIND usando -EXEC e ainda gerar um arquivo?

64

Melhor explicar em exemplos.

Eu posso:

find . -name "*.py" -type f > output.txt

Mas como posso armazenar a saída no mesmo arquivo para:

find . -name "*.py" -type f -exec grep "something" {} \

Não posso simplesmente fazer

find . -name "*.py" -type f -exec grep "something" {} \ > output.txt
bakytn
fonte

Respostas:

106

Se eu entendi direito, é isso que você quer fazer:

find . -name '*.py' -print0 | xargs -0 grep 'something' > output.txt

Findtodos os arquivos com extensão py, grepapenas linhas que contêm somethinge salvam as linhas output.txt. Se o arquivo contiver algo, ele será substituído.

Editar: Usando -exec:

find . -name '*.py' -exec grep 'something' {} \; > output.txt

Estou incorporando o comentário de Chris Downs aqui. O comando acima resultará na grepexecução quantas vezes forem findencontradas as ocorrências. No entanto, se você substituir o ;por a +, grepserá chamado com a saída findconcatenada (até um determinado limite). Veja a pergunta Usando ponto-e-vírgula (;) vs mais (+) com exec para encontrar mais informações sobre o assunto.

johnny
fonte
16
Use em +vez de \;, ele melhorará significativamente o tempo de execução (uma vez que contatenará os argumentos anteriores à execução até ARG_MAX).
Chris Baixo
Agora eu entendo o poder dos xargs! Obrigado!
domih
4
Use grep -Hse você deseja incluir o nome do arquivo do arquivo na saída.
23318 Steinar
18

Se você quiser salvar todas as linhas correspondentes em todos os arquivos output.txt, seu último comando funcionará, exceto que você está perdendo o necessário ;no final do comando.

find . -name "*.py" -type f -exec grep "something" {} \; > output.txt

Se você deseja que cada execução grepproduza saída para um arquivo diferente, execute um shell para calcular o nome do arquivo de saída e executar o redirecionamento.

find . -name "*.py" -type f -exec sh -c 'grep "something" <"$0" >"$0.txt"' {} \;
Gilles 'SO- parar de ser mau'
fonte
o último muito legal: D
bakytn 20/09/11
Para expandir a resposta do @gilles e torná-la um pouco mais informativa, especialmente se a lista de arquivos com os quais você está lidando for grande, você pode relatar o nome do arquivo (caminho relativo) de cada arquivo, juntamente com os resultados em grep'ed usando este : find . -name "*.py" -type f -exec grep "something" {} \; -print > output.txt E se você gostaria de ver os números das linhas grep'ed, você pode, é claro, usargrep -n "something"
JJMpls
9

Para o registro, greptem --includee --excludeargumentos que você pode usar para filtrar os arquivos pesquisados:

grep -r --include="*.py" "something" > output.txt
caçar
fonte
2
Pelo menos o GNU grepfaz.
Phk # 1/16
2

Use tee:

find . -name '*.py' | tee output.txt | xargs grep 'something'

A ressalva, é se você tiver quaisquer arquivos com caracteres especiais (incluindo espaços), que xargse grepnão vai funcionar bem com ( a file.txtserá interpretada como dois arquivos, ae file.txt). A alternativa é usar o -xou -print0, mas qualquer um deles poluirá o seu output.txt. O -xirá usar \para escapar de certos caracteres especiais e isso será exibido output.txt. Ele -print0usará um byte nulo como separador de campos (que também requer xargs -0) e output.txtserá semelhante a uma longa linha de texto contígua.

Como você lida (ou não) com isso depende de você.

bahamat
fonte