Como você contaria cada ocorrência de um termo em todos os arquivos no diretório atual?

10

Como você contaria cada ocorrência de um termo em todos os arquivos no diretório atual? - e subdiretórios (?)

Eu li que para fazer isso você usaria grep; qual é o comando exato?

Além disso, é possível o acima com algum outro comando?

Diga-me o porquê
fonte

Respostas:

12

Usando grep+ wc(isso atende a várias ocorrências do termo na mesma linha):

grep -rFo foo | wc -l
  • -rin grep: pesquisa recursivamente na hierarquia de diretórios atual;
  • -Fin grep: corresponde a uma sequência fixa em vez de a um padrão;
  • -oin grep: imprime apenas correspondências;
  • -lin wc: imprime a contagem das linhas;
% tree                 
.
├── dir
│   └── file2
└── file1

1 directory, 2 files
% cat file1 
line1 foo foo
line2 foo
line3 foo
% cat dir/file2 
line1 foo foo
line2 foo
line3 foo
% grep -rFo foo | wc -l
8
kos
fonte
Eu acho o mais legal.
Jacob Vlijm
1
@JacobVlijm Thanks! Eu também gosto do seu (e já o votei)
kos
Eu acho que PCREsnão deve ser utilizado, uma vez que são experimentais
Edward Torvalds
2
Os PCREs não são "experimentais", mas nem sempre são compilados no grep (e é por isso que eu uso o pcregrep quando preciso deles). Nesse caso, eles são desnecessários, pois a pergunta é sobre um "termo" que provavelmente é uma string fixa, não um padrão de qualquer tipo. Então, -Fprovavelmente seria mais rápido.
22415 Dannysauer #
2
@dannysauer Eu usei PCREs porque, por algum motivo (errado), pensei que eles eram necessários para corresponder a várias ocorrências na mesma linha, mas na verdade não são. Eu apenas não tentei usar em -Fvez de -P. Obrigado pela ótima sugestão, atualizando usando -F, que realmente se encaixa melhor aqui.
kos
8

grep -Rc [term] *vai fazer isso. O -Rsinalizador significa que você deseja pesquisar recursivamente o diretório atual e todos os seus subdiretórios. O *é um seletor de arquivos que significa: todos os arquivos. O -csinalizador produz grepapenas o número de ocorrências. No entanto, se a palavra ocorrer várias vezes em uma única linha, ela será contada apenas uma vez.

De man grep:

  -r, --recursive
          Read all files under each directory, recursively, following symbolic links only if they are on the command line.
          This is equivalent to the -d recurse option.

   -R, --dereference-recursive
          Read all files under each directory, recursively.  Follow all symbolic links, unlike -r.

Se você não possui links simbólicos no seu diretório, não há diferença.

Jos
fonte
você pode adicionar a -cbandeira a grep. Então o grep conta-se e você não precisa dowc
Wayne_Yux 6/15
você pode querer colocar --antes*
Edward Torvalds
2
O *arquivo será expandido apenas para arquivos que não sejam dot-dot; portanto, você perderá todos eles. Faz mais sentido usar apenas "." já que você vai processar argumentos recursivamente de qualquer maneira - e isso obterá arquivos de ponto. O maior problema aqui é que isso pode ser o número de linhas, não o número de ocorrências de uma palavra. Se o termo aparecer várias vezes em uma linha, ele será contado apenas uma vez por "grep -c"
dannysauer 6/11/15
2

Em um pequeno script python:

#!/usr/bin/env python3
import os
import sys

s = sys.argv[1]
n = 0
for root, dirs, files in os.walk(os.getcwd()):
    for f in files:
        f = root+"/"+f      
        try:
            n = n + open(f).read().count(s)
        except:
            pass
print(n)
  • Salve como count_string.py.
  • Execute- o no diretório com o comando:

    python3 /path/to/count_string.py <term>
    

Notas

  • Se o termo incluir espaços, use aspas.
  • Ele conta todas as ocorrências do termo recursivamente, também se houver várias ocorrências em uma linha.

Explicação:

# get the current working directory
currdir = os.getcwd()
# get the term as argument
s = sys.argv[1]
# count occurrences, set start to 0 
n = 0
# use os.walk() to read recursively
for root, dirs, files in os.walk(currdir):
    for f in files:
        # join the path(s) above the file and the file itself
        f = root+"/"+f
        # try to read the file (will fail if the file is unreadable for some reason)
        try:
            # add the number of found occurrences of <term> in the file
            n = n + open(f).read().count(s)
        except:
            pass
print(n)
Jacob Vlijm
fonte
2
O python guy ;) +1
TellMeWhy
1
btw qual é o roote fpara?
TellMeWhy
1
rooté o caminho para o arquivo, incluindo "acima" o diretório atual, fé o arquivo Como alternativa, os.path.join()poderia ser usado, mas é mais detalhado.
Jacob Vlijm
1
E n = n + open(f).read().count(s)?
TellMeWhy
2
Essa parece ser a única resposta que conta todas as ocorrências do termo conforme o OP solicitado. AFAIK, todas as soluções que usam grep contarão todas as linhas nas quais o termo ocorre, portanto, uma linha que inclua o termo três vezes contará apenas como uma ocorrência.
11129 Joe
2

Como uma variante da boa resposta do @ kos, se você estiver interessado em especificar as contagens, poderá usar a -copção grep para contar ocorrências:

$ grep -rFoc foo
file1:3
dir/file2:3
emacs_ftw
fonte