Recursive grep
The regular expression search utility grep has a recursive switch -R, but it may not work like you'd expect.
Suppose want to find the names of all .org files in your current directory and below that contain the text cheese."
You have four files, two in the working directory and two below, that all contain the same string: I like cheese."
$ ls -R .: rootfile.org rootfile.txt sub ./sub: subfile.org subfile.txt
It seems that grep -R can either search all files of the form *.org in the current directory, ignoring the -R switch, or search all files recursively if you don't give it a file glob, but it can't do both.
$ grep -R -l cheese *.org rootfile.org $ grep -R -l cheese . ./rootfile.org ./rootfile.txt ./sub/subfile.org ./sub/subfile.txt
One way to solve this is with find and xargs:
$ find . -name '*.org' | xargs grep -l cheese ./rootfile.org ./sub/subfile.org
I was discussing this with Chris Toomey and he suggested an alternative using a subshell that seems more natural:
grep -l cheese $(find . -name '*.org')
Now the code reads more like an ordinary call to grep. From left to right, it essentially says Search for cheese' in files ending in .org" whereas the version with find reads like Find files whose names end in .org and search them for cheese.'" It's good to understand how both approaches work.
Related postsThe post Recursive grep first appeared on John D. Cook.