Is it possible to both search recursively and with a given file pattern?

I am trying to do the equivalent of

find ./ -name "*.[c|h]" -exec grep -Hn PATTERN {} \;

Obviously you can use grep's -r flag, but when I specify a filename pattern such as:

grep -Hn -r PATTERN *.c

It only looks for *.c files in the current directory, not recursively.

I found this, but it does not talk about specifying filenames: Recursive grep vs find / -type f -exec grep {} \; Which is more efficient/faster?


At least with recent versions of GNU grep, you can use glob patterns in a --include argument

grep -Hrn --include="*.[ch]" PATTERN .

[In GNU grep > 2.11 you may omit the explicit starting directory . when using -r]

  • OSX grep also has that switch though patterns are matched to the full path as opposed to base name in GNU – don_crissti Jan 12 '17 at 17:54
  • I am using FreeBSD, this command just waits for STDIN, even though there is an --include flag. – Farhan Yusufzai Jan 12 '17 at 18:21
  • @FarhanYusufzai that may be due to differences in how grep selects directories for the -r case: even in GNU grep, older versions require an explicit starting directory argument e.g. grep -Hrn --include="*.[ch]" PATTERN . – steeldriver Jan 12 '17 at 18:27

The *.c is expanded by the shell before grep is even run. With a suitably fancy shell (e.g. ZSH, possibly with extendedglob set), one can pre-expand recursively via something like

grep bla **/*.[ch]

But that is a shell solution. Other solutions would be to look at the file detection support in such tools as the silver searcher, codesearch, ripgrep.

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.