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 . -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.