I have a directory hierarchy that contains numerous .gz files. I want to be able to recursively grep them for the string "foo". From what I've read online the following should work:

zgrep -R -H "foo" .

However, this never returns any results. If I replace the dot with the name of a file it does work. For example,

zgrep -R -H "foo" myFile.gz

however, obviously, this no longer will be recursive.

I know "foo" is in some of the files because the following command returns many results:

find . -iname "*.gz" | xargs zgrep "output" | less

Does anyone know why my recursive zgrep command is not working. I'm on a RHEL linux box


The way I usually do is:

zgrep "foo" $(find . -name "*.gz")

or (however, the file name will be printed before each result instead of each line --not just the files with matches--):

find . -name "*.gz" -print -exec zgrep "foo" {} \;

If that command returns "Argument list too long", try this way:

for I in $(find . -name "*.gz"); do zgrep "foo" $I; done
  • 1
    find . -name "*.gz" for cross-platform compatibility on all POSIX systems
    – kos
    May 12 '20 at 22:05
  • @kos: Added the dot for compatibility. Thank you.
    – lepe
    May 13 '20 at 8:24
  • zgrep ... $(find ...) breaks on filenames with spaces or other special characters. I recommend find . -name "*.gz" -exec zgrep "foo" {} +. This prints the filename on each matching line, unlike find ... -exec ... {} \; (another way to print the filename on each matching line is to use zgrep -H, if grep supports it). See also: unix.stackexchange.com/questions/187742/…
    – tom

Your almost there. Try this:

zgrep -R -H "foo" *.gz

EDIT: Hmmmm.... intriguing!

According to my zgrep, -R (Recursive) is not an option. Its simply not supported. Id have a check to see what the man page of your zgrep says.

One alternative, which depends on only one level of subdirectories is to do this:

zcat */*.gz | grep <needle>

But I would suggest that your find command is probably better!

  • When I try that I get: zsh: no matches found: *.gz
    – Nosrettap
    Dec 10 '13 at 22:14

You have to install zutils. This will replace the default and limited zgrep on your system with a recursive-able one.

On debian based systems you run apt-get install zutils then you can zgrep -rH myword . and use most of the other parameters from grep you know and love.

  • Hi down-voter. Would love to know why this is not a good idea. I personally used it and I thought it was great.
    – nzn
    Sep 17 '15 at 7:59
  • (+1) Not sure why the down vote. For those interested, there is a nice explanation about the zutils version vs the gzip version of zgrep here: unix.stackexchange.com/questions/187742/…
    – lepe
    Nov 20 '15 at 5:44

Use sift - it's super-fast.

sift -z foo

-z is for unpacking gzips, it descends into subdirectories by default. Shows filenames also by default (your -H option).

PS. Thanks to your question I discovered this tool today. Just battletested it, apart from the functionality you need, I have a 5x speedup on some production logs when comparing to zgrep.


it also works with:

zgrep "foo" */ *.gz

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.