Search code examples
linuxunixgrepgunzip

How to grep the line number of result of that particular file, from multiple files


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?


Solution

  • 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