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/null
adicionado 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 f
a opção de find
refinar o escopo do find
.
Responder2
Como emesta resposta, você provavelmente estará melhor com:
grep -rnw '/path/to/somewhere/' -e "pattern"
-r
ou-R
é recursivo,-n
é o número da linha e-w
stands 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 /etc
ou 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 find
para 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 find
e grep
nó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 nul
caractere ( \0
) em vez de um caractere de espaço. E a opção correspondente para xargs
recebê-los como nul
nomes 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 -F
que 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 find
e fgrep
com sudo
eles:
$ sudo find ... | xargs -0 sudo fgrep texthere
Ou você pode tentar criar outro -perm
sinalizador 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 -s
obter 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 locate
comando para localizar todos os .txt
arquivos em todo o sistema. O locate
comando 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 find
comando acima pelo locate
quase equivalente:
$ locate '*.txt' -0 | xargs -0 fgrep texthere
A -0
opção (ou --null
em alguns sistemas) corresponde à --print0
opção de find
.