How can I use grep to search multiple unnested directories?
You can concatenate several paths for grep to look for:
grep -r "some string" /code/internal/dev/ /code/public/dev/ /code/tools/
If you want to make maximal use of wildcards (and the hierarchy you posted is complete), you can do
grep -r "some string" /code/{*/dev,tools}/*.cs
Explanation:
The first step done is expansion of the braced list. foo{bar,baz}qux
expands to foobarqux foobazqux
. That is, there's a separate word generated for each comma-separated item in the list, with the prefix and postfix part attached to each. You can see how that works by doing
echo A{1,2,3,4}B
which outputs
A1B A2B A3B A4B
Note that this also works with multiple braces, and also with empty arguments; for example
echo {,1,2}{0,1,2}:{2,3}
gives
0:2 0:3 1:2 1:3 2:2 2:3 10:2 10:3 11:2 11:3 12:2 12:3 20:2 20:3 21:2 21:3 22:2 22:3
So after brace expansion, your command looks like this:
grep -r "some string" /code/*/dev/*.cs /code/tools/*.cs
The next step is wildcard expansion. You already know that for the *.cs
part, but it also works for intermediate directories; moreover, if a /
follows, only directories are matched. Therefore given your hierarchy (and making up file names for the .cs
files), you'll get the command:
grep -r "some string" /code/internal/dev/file1.cs /code/internal/dev/file2.cs /code/public/dev/file3.cs /code/tools/file4.cs /code/tools/file5.cs
Only after all this has happened, grep
is called with this list of arguments (note that the same happens with your original commands; grep
never gets to see the *
; expanding that is completely done by bash
before calling grep
).