Comment comptez-vous chaque occurrence d'un terme dans tous les fichiers du répertoire actuel?

10

Comment comptez-vous chaque occurrence d'un terme dans tous les fichiers du répertoire actuel? - et sous-répertoires (?)

J'ai lu que pour ce faire, vous utiliseriez grep; quelle est la commande exacte?

Est-il également possible de faire ce qui précède avec une autre commande?

Dis moi pourquoi
la source

Réponses:

12

Utiliser grep+ wc(cela répondra à plusieurs occurrences du terme sur la même ligne):

grep -rFo foo | wc -l
  • -rin grep: recherche récursivement dans la hiérarchie de répertoires actuelle;
  • -Fin grep: correspond à une chaîne fixe plutôt qu'à un modèle;
  • -odans grep: imprime uniquement les correspondances;
  • -lin wc: imprime le nombre de lignes;
% 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
la source
Je pense que le plus beau.
Jacob Vlijm
1
@JacobVlijm Merci! J'aime aussi le vôtre (et l'a déjà voté)
kos
Je pense que PCREsne devrait pas être utilisé car ils sont expérimentaux
Edward Torvalds
2
Les PCRE ne sont pas "expérimentaux", mais ils ne sont pas toujours compilés dans grep (c'est pourquoi j'utilise pcregrep quand j'en ai besoin). Dans ce cas, ils ne sont cependant pas nécessaires, car la question porte sur un «terme» qui est probablement une chaîne fixe, et non un modèle d'aucune sorte. Donc, ce -Fserait probablement plus rapide.
dannysauer
2
@dannysauer J'ai utilisé des PCRE parce que, pour une raison (fausse), je pensais qu'ils étaient nécessaires pour faire correspondre plusieurs occurrences sur la même ligne, mais ils ne le sont pas. Je n'ai tout simplement pas essayé d'utiliser -Fau lieu de -P. Merci pour la bonne suggestion, la mise à jour en utilisant -F, qui correspond en effet mieux ici.
kos
8

grep -Rc [term] *Fera cela. L' -Rindicateur signifie que vous souhaitez rechercher récursivement le répertoire actuel et tous ses sous-répertoires. Le *sélecteur de fichiers signifie: tous les fichiers. L' -cindicateur rend la grepsortie uniquement le nombre d'occurrences. Cependant, si le mot apparaît plusieurs fois sur une même ligne, il n'est compté qu'une seule fois.

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.

Si vous n'avez pas de liens symboliques dans votre répertoire, il n'y a pas de différence.

Jos
la source
vous pouvez ajouter le -cdrapeau à grep. Alors grep se compte et vous n'avez pas besoin dewc
Wayne_Yux
vous pourriez vouloir mettre --avant*
Edward Torvalds
2
Le *ne s'étendra qu'aux fichiers non dot, vous manquez donc tous ceux-ci. Il est plus logique d'utiliser simplement "." puisque vous allez de toute façon traiter les arguments de manière récursive - et cela obtiendra des fichiers dot. Le plus gros problème ici est que cela peut avoir le nombre de lignes, pas le nombre d'occurrences d'un mot. Si le terme apparaît plusieurs fois sur une même ligne, il ne sera compté qu'une seule fois par "grep -c"
dannysauer
2

Dans un petit 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)
  • Enregistrez-le sous count_string.py.
  • Exécutez-le à partir du répertoire avec la commande:

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

Remarques

  • Si le terme inclut des espaces, utilisez des guillemets.
  • Il compte chaque occurrence du terme de manière récursive, même si plusieurs occurrences sur une même ligne.

Explication:

# 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
la source
2
Le gars de python ;) +1
TellMeWhy
1
BTW quel est le rootet fpour?
TellMeWhy
1
rootest le chemin d'accès au fichier, y compris "au-dessus" du répertoire courant, fest le fichier. Alternativement, os.path.join()pourrait être utilisé, mais est plus détaillé.
Jacob Vlijm
1
Et n = n + open(f).read().count(s)?
TellMeWhy
2
Cela semble être la seule réponse qui compte toutes les occurrences du terme comme l'OP l'a demandé. AFAIK, toutes les solutions utilisant grep compteront toutes les lignes sur lesquelles le terme apparaît, donc une ligne qui inclut le terme trois fois ne comptera que pour une occurrence.
Joe
2

En variante de la belle réponse de @ kos, si vous souhaitez détailler les nombres, vous pouvez utiliser le -ccommutateur de grep pour compter les occurrences:

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