Come valuteresti ogni ricorrenza di un termine in tutti i file nella directory corrente?


10

Come valuteresti ogni ricorrenza di un termine in tutti i file nella directory corrente? - e sottodirectory (?)

Ho letto che per fare questo useresti grep; qual è il comando esatto?

Inoltre, è possibile quanto sopra con qualche altro comando?

Risposte:


12

Usando grep+ wc(questo soddisferà più occorrenze del termine sulla stessa riga):

grep -rFo foo | wc -l
  • -rin grep: cerca ricorsivamente nella gerarchia di directory corrente;
  • -Fin grep: corrisponde a una stringa fissa anziché a una sequenza;
  • -oin grep: stampa solo le corrispondenze;
  • -lin wc: stampa il conteggio delle linee;
% 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

Penso che il più bello.
Jacob Vlijm,

1
@JacobVlijm Grazie! Anche a me piace la tua (e l'ho già votata)
kos

Penso che PCREsnon dovrebbero essere usati poiché sono sperimentali
Edward Torvalds,

2
I PCRE non sono "sperimentali", ma non sono sempre compilati in grep (motivo per cui utilizzo pcregrep quando ne ho bisogno). In questo caso, tuttavia, non sono necessari, poiché la domanda pone un "termine" che è probabilmente una stringa fissa, non uno schema di alcun tipo. Quindi, -Fprobabilmente sarebbe più veloce.
dannysauer,

2
@dannysauer Ho usato i PCRE perché per qualche (errato) motivo ho pensato che fossero necessari per abbinare più ricorrenze sulla stessa linea, ma in effetti non lo sono. Non ho provato a usare -Finvece di -P. Grazie per il grande suggerimento, l'aggiornamento usando -F, che in effetti si adatta meglio qui.
kos,

8

grep -Rc [term] *lo farà. Il -Rflag indica che si desidera cercare ricorsivamente la directory corrente e tutte le sue sottodirectory. Il *è un significato selettore di file: tutti i file. Il -cflag rende in grepoutput solo il numero di occorrenze. Tuttavia, se la parola appare più volte su una sola riga, viene contata una sola volta.

Da 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 non hai collegamenti simbolici nella tua directory, non c'è differenza.


puoi aggiungere la -cbandiera a grep. Quindi grep conta se stesso e non è necessario ilwc
Wayne_Yux

potresti voler mettere --prima*
Edward Torvalds,

2
Si *espanderà solo a file non dotfile, quindi ti perderai tutti quelli. Ha più senso usare solo "." dal momento che elaborerai gli argomenti in modo ricorsivo comunque - e questo otterrà file dot. Il problema più grande qui è che questa volontà potrebbe il numero di righe, non il numero di occorrenze di una parola. Se il termine appare più volte su una riga, verrà conteggiato una sola volta da "grep -c"
dannysauer,

2

In un piccolo 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)
  • Salva come count_string.py.
  • Eseguilo dalla directory con il comando:

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

Appunti

  • Se il termine include spazi, utilizzare le virgolette.
  • Conta ogni ricorrenza del termine in modo ricorsivo, anche se più ricorrenze in una riga.

Spiegazione:

# 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)

2
The python guy ;) +1
TellMeWhy

1
tra che cosa roote e fper?
TellMePerché il

1
rootè il percorso del file incluso "sopra" la directory corrente, fè il file. In alternativa, os.path.join()potrebbe essere usato, ma è più dettagliato.
Jacob Vlijm,

1
E n = n + open(f).read().count(s)?
TellMePerché il

2
Questa sembra essere l'unica risposta che conta tutte le occorrenze del termine come richiesto dal PO. AFAIK, tutte le soluzioni che utilizzano grep conteranno tutte le righe su cui si verifica il termine, quindi una riga che include il termine tre volte verrà conteggiata come un'unica occorrenza.
Joe,

2

Come variante della bella risposta di @ kos, se sei interessato a dettagliare i conteggi, puoi utilizzare l' -cinterruttore grep per contare le occorrenze:

$ grep -rFoc foo
file1:3
dir/file2:3
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.