grep -R
(exceto o GNU modificado grep
encontrado no OS / X 10.8 e posterior) segue links simbólicos, portanto, mesmo que haja apenas 100 GB de arquivos ~/Documents
, ainda pode haver um link simbólico, /
por exemplo, e você acabará verificando todo o sistema de arquivos, incluindo arquivos gosto /dev/zero
. Use grep -r
com o GNU mais recente grep
ou use a sintaxe padrão:
find ~/Documents -type f -exec grep Milledgeville /dev/null {} +
(no entanto, observe que o status de saída não refletirá o fato de o padrão corresponder ou não).
grep
localiza as linhas que correspondem ao padrão. Para isso, ele precisa carregar uma linha de cada vez na memória. O GNU grep
, ao contrário de muitas outras grep
implementações, não tem limite no tamanho das linhas que lê e suporta a pesquisa em arquivos binários. Portanto, se você tiver um arquivo com uma linha muito grande (ou seja, com dois caracteres de nova linha muito distantes), maior que a memória disponível, ele falhará.
Isso normalmente aconteceria com um arquivo esparso. Você pode reproduzi-lo com:
truncate -s200G some-file
grep foo some-file
Essa é difícil de contornar. Você poderia fazê-lo como (ainda com o GNU grep
):
find ~/Documents -type f -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} +
Isso converte seqüências de caracteres NUL em um caractere de nova linha antes de alimentar a entrada grep
. Isso cobriria os casos em que o problema ocorre devido a arquivos esparsos.
Você pode otimizá-lo fazendo isso apenas para arquivos grandes:
find ~/Documents -type f \( -size -100M -exec \
grep -He Milledgeville {} + -o -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} + \)
Se os arquivos não forem escassos e você tiver uma versão do GNU grep
anterior 2.6
, poderá usar a --mmap
opção As linhas serão mapeadas na memória, em vez de copiadas, o que significa que o sistema sempre pode recuperar a memória paginando as páginas para o arquivo. Essa opção foi removida no GNU grep
2.6
grep
poderá descartar os buffers processados até o momento. Você podegrep
produziryes
indefinidamente sem usar mais do que alguns kilobytes de memória. O problema é o tamanho das linhas.--null-data
opção GNU grep também pode ser útil aqui. Força o uso de NUL em vez de nova linha como um terminador de linha de entrada.Eu costumo fazer
Tentei vários métodos e achei que era o mais rápido. Observe que isso não trata arquivos com espaços com o nome do arquivo muito bem. Se você sabe que esse é o caso e tem uma versão GNU do grep, você pode usar:
Caso contrário, você pode usar:
Qual será
exec
um grep para cada arquivo.fonte
find -print0 | xargs -0 grep -ne 'expression'
find -print0
exargs -0
até agora: todos os três BSD, MINIX 3, Solaris 11, ...Eu posso pensar em algumas maneiras de contornar isso:
Em vez de grepping todos os arquivos de uma vez, faça um arquivo de cada vez. Exemplo:
Se você precisar apenas saber quais arquivos contêm as palavras, faça-o
grep -l
. Como o grep interromperá a pesquisa após o primeiro hit, não será necessário continuar lendo nenhum arquivo enormeSe você quiser o texto real também, poderá inserir dois greps separados:
fonte
grep
gera um delimitador legal nos nomes de arquivo). Você também precisa citar$file
.for
para processar o arquivo como dois argumentos)Estou esperando um disco de 6 TB para procurar dados perdidos e a memória está esgotada - erro. Isso deve funcionar para outros arquivos também.
A solução que encontramos foi ler o disco em pedaços usando dd e grepping os pedaços. Este é o código (big-grep.sh):
fonte