I'm trying to use grep to output the line number of the result from multiple files.
Example:
Name of file 1 is test1.zip
; inside test1.zip
, the content is
123
234
Name of file 2 is test2.zip
; inside test2.zip
, the content is
456
789
Now, this is only a simplified scenario. In the actual scenario, I have multiple files like that.
Right now, I'm doing this:
gunzip -c test* | grep -n 789
The result is
4;789
But what I want to see is
2;789
Because 789 is the second line in its own file, test2.zip
.
How can I achieve this?
Grep only sees a stream of lines and has no way of knowing when a file ends and a new one starts, so it doesn't know about line numbering per file.
Instead of piping the output of gunzip
to grep, you can use zgrep
directly:
$ zgrep -n 789 test*
test2.gz:2:789
If you don't have zgrep
, you can use find
with -exec
as follows:
$ find -name 'test*' -exec bash -c 'gunzip -c "$1" | grep -n 789 ' _ {} \;
2:789
This finds all files matching test*
and runs your pipeline on them. The way to bring a pipeline into find -exec
is spawning a subshell with bash -c 'command' _ {}
and then refer to the filename in command
as $1
.
This does give you the result you asked for, but if you also want the filename, you could have it printed if the -exec
exits successfully:
$ find -name 'test*' -exec bash -c 'gunzip -c "$1" | grep -n 789 ' _ {} \; -print
2:789
./test2.gz