Por que cat $ (encontre / usr / portage -name * .ebuild) | grep RESTRICT - funciona? E encontrar | grep - não?

0

Por que não consigo encontrar o grep? Só ajuda o grepping cat of find. Como eu vejo o programa grep poderia ver algum contexto em que cada comando é executado. Mas é contra-intuitivo para um novato como eu. Quando dado com o argumento grep pode procurar arquivos, mas quando está com pipe (|) - não poderia.

    
por Xsi 17.11.2012 / 15:52

2 respostas

3

O comando find gera uma lista de nomes de caminho que correspondem aos critérios de pesquisa, neste caso, um nome com uma extensão .ebuild . (Mas quibble menor: você precisa de aspas em torno do caractere curinga para que o shell passe para encontrá-lo sem tentar expandi-lo primeiro.) Se você canalizar isso para grep , tudo o que você está fazendo é filtrar essa lista de nomes, não o conteúdo desses arquivos.

Por contraste, a construção cat $(find ...) usa a substituição de comando (essa é a $(...) part) para colar a saída de find (a lista de nomes de caminho que gera) de volta na linha de comando como argumentos para cat , causando cat para gravar o conteúdo desses arquivos no stdout e em grep .

A maneira mais simples de fazer o que você quer seria usar a substituição de comando para passar os nomes para grep diretamente:

grep RESTRICT $(find /usr/portage -name "e.build")
    
por 17.11.2012 / 16:11
1

Para expressar o comando de Nicole Hamilton de uma forma mais concisa, você pode usar o sinalizador -exec no comando find.

find /usr/portage -name '*.ebuild' -exec grep RESTRICT {} \;

Isso passa os nomes dos arquivos correspondentes para o grep com as chaves sendo substituídas pelo nome do arquivo. O '\;' é um escape '; isso é usado para significar o fim do comando.

Desempenho @garyjohn

Esta é uma comparação de diferentes tempos para executar o comando find. Todos esses testes foram executados contra um instantâneo recente do portage ( link ). Eu corri 'encontrar'. e 'grep -Rni. ' antes de cronometrar esses testes, por isso espero que o cache de disco e memória RAM seja simulado em todos os testes.

Aqui está o tempo para os dois comandos:

% time grep RESTRICT $(find . -name "*.ebuild") > /dev/null
grep --color RESTRICT $(find . -name "*.ebuild") > /dev/null  0.05s user 0.13s system 95% cpu 0.192 total

% time find . -name "*.ebuild" -exec grep RESTRICT {} \; > /dev/null
find . -name "*.ebuild" -exec grep RESTRICT {} \; > /dev/null  0.68s user 2.63s system 14% cpu 22.523 total

Como você pode ver, o método cat é muito mais rápido em cerca de 5% do tempo do meu exemplo.

No entanto, se o comando find retornar muitos arquivos, teremos um limite do shell com o comprimento de um único comando. Isso fará com que o comando falhe.

% time grep RESTRICT $(find . -name "*") > /dev/null
zsh: argument list too long: grep
grep --color RESTRICT $(find . -name "*") > /dev/null  0.34s user 0.04s system 99% cpu 0.374 tota

Para ver este limite no uso do seu sistema.

getconf ARG_MAX

Aqui encontra-se a execução com o mesmo glob. Observe que leva muito tempo para ser concluído, mas sai com sucesso.

% time find . -name "*" -exec grep RESTRICT {} \; > /dev/null    
find . -name "*" -exec grep RESTRICT {} \; > /dev/null  2.52s user 11.00s system 12% cpu 1:47.67 total

A maneira ideal de executar este comando é usar xargs.

% time find . -name "*" -print0 | xargs -0 grep RESTRICT > /dev/null 
find . -name "*" -print0  0.16s user 0.29s system 51% cpu 0.886 total
xargs -0 grep RESTRICT > /dev/null  0.33s user 0.59s system 100% cpu 0.915 total

Usando o xargs, é possível percorrer toda a árvore do portage (~ 159995 arquivos, 724M) em pouco menos de 2 segundos.

    
por 17.11.2012 / 17:41

Tags