Mostrar el nombre del archivo antes de la línea coincidente

282

¿Cómo puedo grepmostrar el nombre del archivo antes de las líneas coincidentes en su salida?

Vivek
fuente
2
por favor díganos su versión grepgrep --version
Kent
3
Kent, ¿ grep --versiones ese el comando que se utilizará para conocer la versión grep? Si es así, no está funcionando. No se pudo encontrar ningún otro comando para conocer la versión grep.
Vivek
2
buena pregunta, pero 'Os version' es un nombre de archivo de ejemplo confuso
HaveAGuess
1
El sistema operativo y la versión son irrelevantes aquí.
MD XF
grep 'pattern' *
usuario0

Respuestas:

430

Pruebe este pequeño truco para convencerlo de grepque se trata de varios archivos, de modo que muestre el nombre del archivo:

grep 'pattern' file /dev/null

Para obtener también el número de línea:

grep -n 'pattern' file /dev/null
Escrutador
fuente
66
Sí, funcionó. ¿Me puede decir cuál es el significado de agregar /dev/nulleste comando?
Vivek
55
Si grepse suministra con varios nombres de archivo, mostrará automáticamente los nombres de archivo antes de la coincidencia, pero dejará el nombre de archivo en caso de un solo archivo de entrada. Al utilizar /dev/nullcomo un archivo de entrada adicional grep"piensa" que tratar con múltiples archivos, pero / dev / null es, por supuesto, vaciar, por lo que no se mostrará en la lista de coincidencias ..
Scrutinizer
32
usar / dev / null es un truco inteligente, pero creo que la sugerencia a continuación de la bandera -H es una mejor respuesta.
JohnQ
22
OK, pero la -Hopción para grep no es parte de POSIX, y el sistema operativo utilizado es Solaris 10, donde ni el grep estándar ni la versión de grep compatible con POSIX tienen la -Hopción.
Escrutinio
44
Eso es importante si está utilizando grep con find, como find . -name foo -exec grep pattern {} \;: suponiendo que haya muchos archivos nombrados fooen su subdirectorio, findaún entrega grepun solo archivo para operar a la vez. El /dev/nulltruco parece funcionar en todos los sabores de linux / osx que he probado, ¡así que felicitaciones! Tenga en cuenta que creo que -Hes más limpio, pero como se menciona a continuación, puede que no sea compatible con su versión de grep.
Jon V
296

Si tiene las opciones -Hy está -ndisponible ( man grepes su amigo):

$ cat file
foo
bar
foobar

$ grep -H foo file
file:foo
file:foobar

$ grep -Hn foo file
file:1:foo
file:3:foobar

Opciones:

-H, --with-filename

Imprima el nombre del archivo para cada partido. Este es el valor predeterminado cuando hay más de un archivo para buscar.

-n, - número-línea

Prefije cada línea de salida con el número de línea basado en 1 dentro de su archivo de entrada. (-n está especificado por POSIX).

-Hes una extensión de GNU, pero -nestá especificada por POSIX

Chris Seymour
fuente
3
No, -Hno es compatible aquí.
Vivek
1
Compatible pero siempre da grep: file: No
existe
2
funciona en ubuntu -H y -n. Probablemente con todas las versiones más nuevas de * nix
tgkprog
1
¡He luchado con eso durante años sin pensar que había estas opciones!
GreenSaguaro
45

No es necesario un truco.

grep --with-filename 'pattern' file

Con números de línea:

grep -n --with-filename 'pattern' file
MD XF
fuente
3
@codeforester No conozco ningún otro greps, así que no sé.
MD XF
2
Frio ! Esto funcionó para Linux. si usa mac, puede instalar coreutils con brew. Y recuerde agregar PATH = "/ usr / local / opt / coreutils / libexec / gnubin: $ PATH" al suyo .bashrc
zw963
2
Esto (también) funcionó en MinGW (1.0.17, creo).
Peter Mortensen
Funciona para mí con el Mac grep incorporado (2.5.1-FreeBSD). Pero para usar el grep alternativo de Homebrew, otra forma es ejecutar brew install grepy luego simplemente usar ggrep. No es necesario modificar la RUTA.
wonderlr
5

¿Qué tal esto, que logré lograr gracias, en parte, a esta publicación?

Desea encontrar varios archivos, digamos registros con diferentes nombres pero con un patrón (por ejemplo filename=logfile.DATE), dentro de varios directorios con un patrón (por ejemplo /logsapp1, /logsapp2). Cada archivo tiene un patrón que desea grep (por ejemplo "init time"), y desea tener el "init time"de cada archivo, pero sabiendo a qué archivo pertenece.

find ./logsapp* -name logfile* | xargs -I{} grep "init time" {} \dev\null | tee outputfilename.txt

Entonces el outputfilename.txtsería algo como

./logsapp1/logfile.22102015: init time: 10ms
./logsapp1/logfile.21102015: init time: 15ms
./logsapp2/logfile.21102015: init time: 17ms
./logsapp2/logfile.22102015: init time: 11ms

En general

find ./path_pattern/to_files* -name filename_pattern* | xargs -I{} grep "grep_pattern" {} \dev\null | tee outfilename.txt

Explicación:

find el comando buscará los nombres de archivo basados ​​en el patrón

entonces, la tubería xargs -I{}redirigirá la findsalida a la{}

cual será la entrada para grep ""pattern" {}

Luego el truco para hacer grepmostrar los nombres de archivo\dev\null

y finalmente, escriba la salida en el archivo con tee outputfile.txt

Esto funcionó para mí en la grepversión 9.0.5, compilación 1989.

Lejuanjowski
fuente
3
O simplemente usando findfind ./path_pattern/to_files -type f -name "files*.log" -exec grep -Hn pattern {} \;
Martin
1

Esta es una ligera modificación de una solución anterior. Mi ejemplo busca la redirección de stderr en los scripts de bash: grep '2>' $(find . -name "*.bash")

Richard Jessop
fuente
-7
grep 'search this' *.txt

funcionó para mí buscar en todos los archivos .txt (ingrese su propio valor de búsqueda, por supuesto).

MagicMojo
fuente