¿Cómo contaría cada aparición de un término en todos los archivos en el directorio actual?

10

¿Cómo contaría cada aparición de un término en todos los archivos en el directorio actual? - y subdirectorios (?)

He leído que para hacer esto usarías grep; ¿Cuál es el comando exacto?

Además, ¿es posible lo anterior con algún otro comando?

Dime por qué
fuente

Respuestas:

12

Usando grep+ wc(esto atenderá múltiples ocurrencias del término en la misma línea):

grep -rFo foo | wc -l
  • -rin grep: busca recursivamente en la jerarquía de directorios actual;
  • -Fin grep: coincide con una cadena fija en lugar de con un patrón;
  • -oen grep: imprime solo coincidencias;
  • -len wc: imprime el recuento de las líneas;
% 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
fuente
Creo que el mejor.
Jacob Vlijm el
1
@JacobVlijm ¡Gracias! También me gusta el tuyo (y ya lo voté)
kos
Creo que no PCREsdebería usarse ya que son experimentales
Edward Torvalds
2
Los PCRE no son "experimentales", pero tampoco siempre se compilan en grep (por eso uso pcregrep cuando los necesito). Sin embargo, en este caso, son innecesarios, ya que la pregunta se refiere a un "término" que probablemente sea una cadena fija, no un patrón de ningún tipo. Entonces, -Fprobablemente sería más rápido.
dannysauer
2
@dannysauer Usé PCRE porque por alguna razón (equivocada) pensé que eran necesarios para hacer coincidir múltiples ocurrencias en la misma línea, pero de hecho no lo son. Simplemente no intenté usar en -Flugar de -P. Gracias por la gran sugerencia, la actualización usando -F, que de hecho encaja mejor aquí.
Kos
8

grep -Rc [term] *lo haré. El -Rindicador significa que desea buscar de forma recursiva el directorio actual y todos sus subdirectorios. El *es un selector de archivos que significa: todos los archivos. La -cbandera hace que la grepsalida solo sea el número de ocurrencias. Sin embargo, si la palabra aparece varias veces en una sola línea, solo se cuenta una vez.

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 no tiene enlaces simbólicos en su directorio, no hay diferencia.

Jos
fuente
puedes agregar la -cbandera a grep. Entonces grep cuenta y no necesitas elwc
Wayne_Yux
es posible que desee poner --antes*
Edward Torvalds
2
La *única ampliará a los no comienzan con un punto, por lo que se le pasa a todos aquellos. Tiene más sentido simplemente usar "." ya que de todos modos va a procesar argumentos de forma recursiva, y eso obtendrá archivos de puntos. El mayor problema aquí es que esto podría ser el número de líneas, no el número de apariciones de una palabra. Si el término aparece varias veces en una línea, solo se contará una vez por "grep -c"
dannysauer
2

En un pequeño script de 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)
  • Guárdalo como count_string.py.
  • Ejecútelo desde el directorio con el comando:

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

Notas

  • Si el término incluye espacios, use comillas.
  • Cuenta cada ocurrencia del término de forma recursiva, también si ocurre varias veces en una línea.

Explicación:

# 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
fuente
2
The python guy ;) +1
TellMeWhy
1
por cierto, ¿para qué rooty fpara qué?
TellMeWhy
1
rootes la ruta al archivo que incluye "arriba" del directorio actual, fes el archivo. Alternativamente, os.path.join()podría usarse, pero es más detallado.
Jacob Vlijm el
1
Y n = n + open(f).read().count(s)?
TellMeWhy
2
Esta parece ser la única respuesta que cuenta todas las apariciones del término como lo solicitó el OP. AFAIK, todas las soluciones que utilizan grep contarán todas las líneas en las que aparece el término, por lo que una línea que incluya el término tres veces solo contará como una ocurrencia.
Joe
2

Como una variante de la buena respuesta de @ kos, si está interesado en detallar los recuentos, puede usar el -cinterruptor de grep para contar las ocurrencias:

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