Wie würden Sie jedes Vorkommen eines Begriffs in allen Dateien im aktuellen Verzeichnis zählen?


10

Wie würden Sie jedes Vorkommen eines Begriffs in allen Dateien im aktuellen Verzeichnis zählen? - und Unterverzeichnisse (?)

Ich habe gelesen, dass Sie dazu verwenden würden grep; Was ist der genaue Befehl?

Ist es auch möglich, dies mit einem anderen Befehl zu tun?

Antworten:


12

Verwenden von grep+ wc(dies berücksichtigt mehrere Vorkommen des Begriffs in derselben Zeile):

grep -rFo foo | wc -l
  • -rin grep: sucht rekursiv in der aktuellen Verzeichnishierarchie;
  • -Fin grep: Übereinstimmungen mit einer festen Zeichenfolge anstelle eines Musters;
  • -oin grep: druckt nur Übereinstimmungen;
  • -lin wc: druckt die Anzahl der Zeilen;
% 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

Ich denke das schönste.
Jacob Vlijm

1
@ JacobVlijm Danke! Ich mag deine auch (und habe sie bereits positiv bewertet)
kos

Ich denke, PCREssollte nicht verwendet werden, da sie experimentell sind
Edward Torvalds

2
PCREs sind nicht "experimentell", aber sie werden auch nicht immer in grep kompiliert (weshalb ich pcregrep verwende, wenn ich sie brauche). In diesem Fall sind sie jedoch unnötig, da in der Frage nach einem "Begriff" gefragt wird, bei dem es sich wahrscheinlich um eine feste Zeichenfolge handelt, nicht um ein Muster. Also -Fwäre wohl schneller.
Dannysauer

2
@dannysauer Ich habe PCREs verwendet, weil ich aus irgendeinem (falschen) Grund dachte, dass sie benötigt werden , um mehrere Vorkommen in derselben Zeile abzugleichen , aber in der Tat sind sie es nicht. Ich versuche einfach nicht mit -Fstatt -P. Vielen Dank für den tollen Vorschlag, mit zu aktualisieren -F, der hier tatsächlich besser passt.
Kos

8

grep -Rc [term] *wird das machen. Das -RFlag bedeutet, dass Sie das aktuelle Verzeichnis und alle seine Unterverzeichnisse rekursiv durchsuchen möchten. Das *ist eine Dateiauswahl, die bedeutet: alle Dateien. Das -cFlag gibt grepnur die Anzahl der Vorkommen aus. Wenn das Wort jedoch mehrmals in einer einzelnen Zeile vorkommt, wird es nur einmal gezählt.

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

Wenn Sie keine symbolischen Links in Ihrem Verzeichnis haben, gibt es keinen Unterschied.


Sie können die -cFlagge hinzufügen grep. Dann zählt sich grep selbst und Sie brauchen daswc
Wayne_Yux

Vielleicht möchten Sie setzen --vor*
Edward Torvalds

2
Das *wird nur auf Nicht-Dotfiles erweitert, so dass Sie alle diese vermissen. Es ist sinnvoller, nur "." da du Argumente sowieso rekursiv verarbeiten wirst - und das wird Punktdateien bekommen. Das größere Problem hierbei ist, dass dies die Anzahl der Zeilen und nicht die Anzahl der Vorkommen eines Wortes sein kann. Wenn der Begriff mehrmals in einer Zeile vorkommt, wird er von "grep -c"
dannysauer

2

In einem kleinen Python-Skript:

#!/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)
  • Speichern Sie es als count_string.py.
  • Führen Sie es mit dem folgenden Befehl aus dem Verzeichnis aus :

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

Anmerkungen

  • Wenn der Begriff Leerzeichen enthält, verwenden Sie Anführungszeichen.
  • Es zählt jedes Vorkommen des Begriffs rekursiv, auch wenn mehrere Vorkommen in einer Zeile vorhanden sind.

Erläuterung:

# 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
Der Python-Typ ;) +1
TellMeWhy

1
Übrigens, was ist das rootund wofür f?
TellMeWhy

1
rootist der Pfad zur Datei einschließlich "über" dem aktuellen Verzeichnis, fist die Datei. Alternativ os.path.join()könnte verwendet werden, ist aber ausführlicher.
Jacob Vlijm

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

2
Dies scheint die einzige Antwort zu sein, die alle Vorkommen des Begriffs als angefordertes OP zählt. AFAIK, alle Lösungen, die grep verwenden, zählen alle Zeilen, in denen der Begriff vorkommt, sodass eine Zeile, die den Begriff dreimal enthält, nur als ein Vorkommen zählt.
Joe

2

Als Variante der netten Antwort von @ kos können Sie, wenn Sie daran interessiert sind, die Anzahl aufzulisten, den -cSchalter von grep verwenden , um Vorkommen zu zählen:

$ grep -rFoc foo
file1:3
dir/file2:3
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.