Usé esto mucho, la mejora que trato de lograr es evitar nombres de archivos de eco que no coinciden en grep. ¿Mejor forma de hacer esto?
for file in `find . -name "*.py"`; do echo $file; grep something $file; done
Comentarios
- Relacionados (en Preguntar a Ubuntu ): ¿Buscar de forma recursiva un patrón / texto solo en el nombre de archivo especificado de un directorio?
Respuesta
find . -name "*.py" -exec grep something {} \; -print
imprimiría el nombre del archivo después de las líneas coincidentes.
find . -name "*.py" -exec grep something /dev/null {} +
imprimiría el nombre del archivo delante de cada línea coincidente (agregamos /dev/null
para el caso en el que solo haya una archivo coincidente como grep
no imprime el nombre del archivo si solo se ha pasado un archivo para buscar. La implementación GNU de grep
tiene una -H
opción para eso como alternativa).
find . -name "*.py" -exec grep -l something {} +
imprimiría solo los nombres de archivo de los archivos que tienen al menos una línea coincidente.
Para imprimir el nombre del archivo antes de las líneas coincidentes, puede usar awk en su lugar:
find . -name "*.py" -exec awk " FNR == 1 {filename_printed = 0} /something/ { if (!filename_printed) { print FILENAME filename_printed = 1 } print }" {} +
O llame a grep
dos veces para cada archivo, aunque eso «sería menos eficiente ya que ejecutaría al menos un comando grep
y hasta dos para cada archivo (y leería el contenido del archivo dos veces ):
find . -name "*.py" -exec grep -l something {} \; \ -exec grep something {} \;
En cualquier caso, no desea recorrer la salida de find
así y recuerde citar su variables .
Si desea utilizar un ciclo de shell, con herramientas GNU:
find . -name "*.py" -exec grep -l --null something {} + | xargs -r0 sh -c " for file do printf "%s\n" "$file" grep something < "$file" done" sh
(también funciona en FreeBSD y derivados).
Respuesta
I Si está usando GNU grep, puede usar su opción -r
o --recursive
para hacer esta búsqueda simple por usted:
grep -r --include "*.py" -le "$regexp" ./ # for filenames only grep -r --include "*.py" -He "$regexp" ./ # for filenames on each match
Solo necesita find
si lo necesita predicados más avanzados.
Comentarios
- Dependiendo de la versión de GNU
grep
,grep
puede o no mirar dentro de enlaces simbólicos o atravesar enlaces simbólicos a directorios. También puede encontrar algunas variaciones en el manejo de otros tipos de archivos no regulares.
Responder
Usted puede decirle a grep que incluya el nombre del archivo en la salida. Entonces, si hay una coincidencia, se mostrará en la consola; si no hay ninguna coincidencia dentro de un archivo, no se imprimirá ninguna línea para ese archivo.
find . -name "*.py" | xargs grep -n -H something
Desde man grep
:
-H Always print filename headers with output lines -n, --line-number Each output line is preceded by its relative line number in the file, starting at line 1. The line number counter is reset for each file processed. This option is ignored if -c, -L, -l, or -q is specified.
Si sus archivos pueden tener nombres con espacios, debe cambiar la tubería para usar caracteres NUL como separador. El comando completo ahora se verá así:
find . -name "*.py" -print0 | xargs -0 grep -n -H something
Responder
Puede intente algo como:
find . -name "*.py:" -exec grep -l {} \;
Este comando exec grep para cada archivo, descubierto por el comando de búsqueda y su función de comando de búsqueda estándar
Respuesta
Utilice el argumento -l
.
for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done
Un uso más interesante sería:
for file in $(find . -name "*.py" -exec grep -l something "{}" +); do echo "$file"; grep something $file; done
Responder
Allí son grep
alternativas que, por defecto, muestran sus resultados en el formato que desee. Los 2 más populares que conozco son ag
(también conocido como «el buscador de plata») y ack
. ag
se anuncia como una alternativa más rápida a ack
.
$ ag "^\w+\s*\w+\(" ~/build/i3/src build/i3/src/display_version.c 58:void display_running_version(void) { build/i3/src/load_layout.c 42:static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings = 518:json_content_t json_determine_content(const char *filename) { 575:void tree_append_json(Con *con, const char *filename, char **errormsg) { build/i3/src/x.c 64:CIRCLEQ_HEAD(state_head, con_state) state_head = 67:CIRCLEQ_HEAD(old_state_head, con_state) old_state_head = 70:TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head = 97:void x_con_init(Con *con, uint16_t depth) { ...
No puedo mostrarte aquí, pero la salida está bien coloreada. Obtengo los nombres de archivo en verde oliva, los números de línea en amarillo dorado y la pieza correspondiente en cada línea en rojo sangre. Sin embargo, los colores son personalizables.