Como usar o grep para pesquisar texto em TODAS as pastas?

Como usar o grep para pesquisar texto em TODAS as pastas?

Estou tendo problemas para pesquisar TODOS os diretórios de uma vez com o grep. Quando uso o comando:

find . -name "*.txt" | xargs grep texthere

Demora uma eternidade e depois me dá erros "nenhum arquivo ou diretório".

Por que isso está acontecendo e não há nada mais fácil do que grep? Ou estou usando o comando errado?

Responder1

Se você possui GNU grep, o próprio grep suporta a opção "-r" para pesquisar recursivamente, conforme sugerido por @Ouroborus.

Se infelizmente o seu grep não suporta essa opção, como no SunOS, você pode usar os seguintes comandos:

find . -name "*.txt" -exec grep -n your_pattern {} /dev/null \;

O truque é /dev/nulladicionado para garantir que cada execução do grep tenha dois arquivos (o arquivo correspondente a *.txt e o /dev/null) fornecidos, forçando-o a imprimir o nome dos arquivos que estão sendo pesquisados. E você pode adicionar -type fa opção de findrefinar o escopo do find.

Responder2

Como emesta resposta, você provavelmente estará melhor com:

grep -rnw '/path/to/somewhere/' -e "pattern"

  • -rou -Ré recursivo,
  • -né o número da linha e
  • -wstands correspondem à palavra inteira.
  • -l(L minúsculo) pode ser adicionado apenas para fornecer o nome do arquivo correspondente.

Responder3

Se você estiver recebendo erros sobre permissões (você não diz que sim), então suponho que você esteja no diretório raiz ( /) ou em algum caminho onde não tem permissão para ler todos os arquivos, como em /etcou em /var. Mas como você diz que leva muito tempo, estou mais inclinado para a primeira suposição (o diretório raiz).

Se você quiser pesquisar absolutamentetodosarquivos notodosistema, do que o que você está fazendo está certo. Istovaidemore muito, não importa o que você faça. São muitos arquivos para pesquisar.

Você pode usar findpara restringir a quantidade de arquivos a serem visualizados.

No momento, você tem

$ find . -name "*.txt" | xargs grep texthere

Como parece que você está interessado apenas em arquivos de texto simples, podemos excluir qualquer outro tipo de arquivo (executáveis):

$ find / -type f \! -perm -o=x -name "*.txt" | xargs grep texthere

Troquei .por /aqui, porque é onde eupensarvocê é (corrija-me se eu estiver errado). Também estou especificando que queroarquivos( -type f) que sãonão executável( \! -perm -o=x) ( !precisa ser escapado para que seu shell não faça coisas engraçadas com ele).

Agora, há mais algumas coisas que podemos fazer. Um é uma questão de segurança e o outro podepossivelmentemelhorar um pouco a velocidade.

Alguns nomes de arquivos podem conter espaços ou outros caracteres instáveis ​​que normalmente não queremos em nomes de arquivos. Para poder passá-los corretamente entre finde grepnós fazemos

$ find / -type f \! -perm -o=x -name "*.txt" -print0 | xargs -0 grep texthere

Isto ( -print0) significa que cada nome de arquivo será delimitado por um nulcaractere ( \0) em vez de um caractere de espaço. E a opção correspondente para xargsrecebê-los como nulnomes de arquivos delimitados é -0.

É porque você não está usando essas duas opções que acredito que você receba os erros "nenhum arquivo ou diretório".

A questão da velocidade é fgrep. Este é um utilitário exatamente equivalente ao grep -Fque você deve usar se sua string de pesquisa for uma string de texto simples sem expressões regulares.

Portanto, se você tiver uma string de texto simples e quiser procurá-la em cada arquivo de todo o sistema:

$ find / -type f \! -perm -o=x -name "*.txt" -print0 | xargs -0 fgrep texthere

A questão da permissão... Obviamente haverá arquivos que você não conseguirá ler. Você pode executar finde fgrepcom sudoeles:

$ sudo find ... | xargs -0 sudo fgrep texthere

Ou você pode tentar criar outro -permsinalizador find(e também fazer com que ele ignore diretórios nos quais você não pode entrar), mas isso consumiria muito tempo e resultaria em uma linha de comando ridiculamente longa, então não farei isso aqui.

Ou você poderia simplesmente sudo -sobter um shell root e executá-lo a partir daí... mas eu geralmente desaconselho isso porque as pessoas têm a tendência de bagunçar seus sistemas esquecendo que são root.

OUTRA SOLUÇÃOseria usar o locatecomando para localizar todos os .txtarquivos em todo o sistema. O locatecomando não pesquisa a hierarquia de arquivos, mas usa um banco de dados (que geralmente é atualizado diariamente, portanto, nãotodosarquivos podem estar lá). O banco de dados contém apenas arquivos em diretórios acessíveis a todos os usuários; portanto, se você removeu as permissões de leitura em seus próprios diretórios, seus arquivos não estarão lá.

Então, substituindo o findcomando acima pelo locatequase equivalente:

$ locate '*.txt' -0 | xargs -0 fgrep texthere

A -0opção (ou --nullem alguns sistemas) corresponde à --print0opção de find.

informação relacionada