Bagaimana Anda menghitung setiap kemunculan istilah di semua file di direktori saat ini?

10

Bagaimana Anda menghitung setiap kemunculan istilah di semua file di direktori saat ini? - dan subdirektori (?)

Saya sudah membaca bahwa untuk melakukan ini Anda akan menggunakan grep; apa perintah tepatnya?

Juga, apakah mungkin untuk yang di atas dengan beberapa perintah lain?

TellMeWhy
sumber

Jawaban:

12

Menggunakan grep+ wc(ini akan memenuhi beberapa kejadian istilah pada baris yang sama):

grep -rFo foo | wc -l
  • -rdi grep: mencari secara rekursif dalam hierarki direktori saat ini;
  • -Fdi grep: cocok dengan string tetap dan bukan terhadap pola;
  • -odi grep: hanya mencetak yang cocok;
  • -ldi wc: mencetak hitungan garis;
% 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
sumber
Saya pikir yang terbaik.
Jacob Vlijm
1
@JacobVlijm Terima kasih! Saya juga menyukai milik Anda (dan sudah memutarnya)
kos
Saya pikir PCREstidak boleh digunakan karena mereka eksperimental
Edward Torvalds
2
PCRE tidak "eksperimental", tetapi mereka juga tidak selalu dikompilasi untuk grep (itulah sebabnya saya menggunakan pcregrep saat saya membutuhkannya). Dalam kasus ini, mereka tidak perlu, karena pertanyaannya adalah tentang "istilah" yang kemungkinan merupakan string tetap, bukan pola apa pun. Jadi, -Fmungkin akan lebih cepat.
dannysauer 6-15
2
@ Dannysauer Saya menggunakan PCRE karena untuk beberapa (salah) alasan saya pikir mereka diperlukan untuk mencocokkan beberapa kejadian pada baris yang sama, tetapi memang tidak. Aku hanya tidak mencoba menggunakan -Fbukan -P. Terima kasih atas saran bagus, memperbarui penggunaan -F, yang memang lebih cocok di sini.
kos
8

grep -Rc [term] *akan melakukan itu. Tanda itu -Rberarti Anda ingin secara rekursif mencari direktori saat ini dan semua subdirektori. Ini *adalah arti pemilih file: semua file. The -cflag membuat grepkeluaran hanya jumlah kejadian. Namun, jika kata itu muncul beberapa kali dalam satu baris, itu hanya dihitung sekali.

Dari 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.

Jika Anda tidak memiliki tautan simbolis di direktori Anda, tidak ada perbedaan.

Jos
sumber
Anda dapat menambahkan -cbendera ke grep. Kemudian grep menghitung dengan sendirinya dan Anda tidak perluwc
Wayne_Yux
Anda mungkin ingin menempatkan --sebelum*
Edward Torvalds
2
Hanya *akan diperluas ke non-dotfile, jadi Anda melewatkan semua itu. Lebih masuk akal untuk menggunakan "." karena Anda akan memproses argumen secara rekursif - dan itu akan mendapatkan file dot. Masalah yang lebih besar di sini adalah bahwa ini akan bisa jumlah baris, bukan jumlah kemunculan kata. Jika istilah tersebut muncul beberapa kali dalam satu baris, itu hanya akan dihitung sekali oleh "grep -c"
dannysauer
2

Dalam skrip python kecil:

#!/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)
  • Simpan sebagai count_string.py.
  • Jalankan dari direktori dengan perintah:

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

Catatan

  • Jika istilahnya termasuk spasi, gunakan tanda kutip.
  • Ini menghitung setiap kemunculan istilah secara rekursif, juga jika beberapa kemunculan dalam satu baris.

Penjelasan:

# 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)
Yakub Vlijm
sumber
2
The python guy ;) +1
TellMeWhy
1
btw untuk apa rootdan f?
TellMeWhy
1
rootadalah path ke file termasuk "di atas" direktori saat ini, fadalah file. Atau, os.path.join()bisa digunakan, tetapi lebih verbose.
Jacob Vlijm
1
Dan n = n + open(f).read().count(s)?
TellMeWhy
2
Tampaknya ini adalah satu-satunya jawaban yang menghitung semua kemunculan istilah seperti yang diminta OP. AFAIK, semua solusi menggunakan grep akan menghitung semua garis di mana istilah tersebut muncul, sehingga garis yang mencakup istilah tiga kali hanya akan dihitung sebagai satu kejadian.
Joe
2

Sebagai varian jawaban bagus @ kos, jika Anda tertarik merinci penghitungan, Anda dapat menggunakan -csakelar grep untuk menghitung kemunculan:

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