Як би ви порахували кожне виникнення терміна у всіх файлах у поточному каталозі?


10

Як би ви порахували кожне виникнення терміна у всіх файлах у поточному каталозі? - і підкаталоги (?)

Я читав, що для цього ви б скористалися grep; яка точна команда?

Також, чи можливо вищезазначене за допомогою якоїсь іншої команди?

Відповіді:


12

Використання grep+ wc(це вплине на кілька випадків виникнення терміна в одному рядку):

grep -rFo foo | wc -l
  • -rв grep: рекурсивно здійснює пошук у поточній ієрархії каталогів;
  • -Fв grep: збігається з фіксованим рядком замість візерунка;
  • -oу grep: друкує лише сірники;
  • -lв wc: друкує кількість ліній;
% 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

Я думаю, що найприємніше.
Яків Влійм

1
@JacobVlijm Дякую! Мені теж подобається ваш (і вже його схвалив)
kos

Думаю, PCREsне слід їх використовувати, оскільки вони експериментальні
Едвард Торвальдс

2
PCRE не є "експериментальними", але вони також не завжди збираються в grep (саме тому я використовую pcregrep, коли мені це потрібно). У цьому випадку вони непотрібні, оскільки питання задає питання про "термін", який, ймовірно, є фіксованим рядком, а не будь-яким шаблоном. Так, -Fпевно , було б швидше.
dannysauer

2
@dannysauer Я використовував PCRE, тому що з якихось (неправильних) причин я вважав, що вони потрібні для відповідності декількох випадків на одній лінії, але насправді вони не є. Я просто не намагався використовувати -Fзамість цього -P. Дякуємо за чудову пропозицію, оновлення використання -F, яка справді краще підходить тут.
kos

8

grep -Rc [term] *зробимо це. -RПрапор означає , що ви хочете рекурсивно шукати в поточному каталозі і всіх його підкаталогах. *Є селектор файлів сенс: всі файли. -cПрапора робить grepвиводити тільки число входжень. Однак якщо слово зустрічається кілька разів на одному рядку, воно рахується лише один раз.

Від 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.

Якщо у вашому каталозі немає символічних посилань, різниці немає.


ви можете додати -cпрапор до grep. Тоді греп рахує себе, і вам не потрібноwc
Wayne_Yux

ви могли б хотіти поставити --раніше*
Едвард Торвальдс

2
*Буде розширюватися тільки для НЕ складають приховані, так що ви пропустите всі ті. Більше сенсу просто використовувати "". оскільки ви все одно будете обробляти аргументи рекурсивно - і ви отримаєте крапкові файли. Більшою проблемою тут є те, що це може мати кількість рядків, а не кількість зустрічань слова. Якщо термін відображається кілька разів на одному рядку, він буде рахуватися лише один раз "grep -c"
dannysauer

2

У невеликому сценарії 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)
  • Збережіть як count_string.py.
  • Запустіть його з каталогу за допомогою команди:

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

Примітки

  • Якщо термін включає пробіли, використовуйте лапки.
  • Він підраховує кожне виникнення терміна рекурсивно, також якщо кілька випадків в одному рядку.

Пояснення:

# 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
Хлопець пітона ;) +1
TellMeWhy

1
btw для чого rootі fдля чого?
TellMeWhy

1
root- це шлях до файлу, що включає "вище" поточного каталогу, f- файл. Як варіант, os.path.join()можна використовувати, але є більш багатослівним.
Яків Влійм

1
І n = n + open(f).read().count(s)?
TellMeWhy

2
Здається, це єдина відповідь, яка враховує всі випадки цього терміна як запиту ОП. AFAIK, усі рішення, що використовують grep, будуть рахувати всі рядки, в яких виникає термін, тому лінія, що включає в себе термін тричі, буде вважатися лише одним явищем.
Джо

2

Як варіант приємної відповіді @ kos, якщо ви зацікавлені в деталізації підрахунків, ви можете використовувати -cперемикач grep для підрахунку подій:

$ grep -rFoc foo
file1:3
dir/file2:3
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.