Louis I. answered 04/27/19
Computer Science Instructor/Tutor: Real World and Academia Experienced
I can think of 2 slightly different ways of doing this ... both involve using the "find" command.
The first approach asks "find" to generate a list of file paths used as arguments to grep:
grep "import java\.util\." $(find . -type f -name "*.java" )
./src/edu/cuny/csi/csc330/threads/BasicThreadPool.java:import java.util.concurrent.Executors;
./src/edu/cuny/csi/csc330/threads/BasicThreadPool.java:import java.util.concurrent.Future;
./src/edu/cuny/csi/csc330/threads/RunnableBufferWriter.java:import java.util.Date;
./src/test.java:import java.util.*;
But this can be problematic as the shell command-line size has a typical limit of 100s of K-Bytes ... file path can be long, and find might returns 10's or 100's thousands of files.
So another way to use "find" which gets around this limitation is as follows - it involves using a short custom script and the "-exec" option on the "find" command:
find . -type f -name "*.java" -exec ./mygrep "import java\.util\." {} \;
./src/edu/cuny/csi/csc330/threads/BasicThreadPool.java:import java.util.concurrent.Executors;
./src/edu/cuny/csi/csc330/threads/BasicThreadPool.java:import java.util.concurrent.Future;
./src/edu/cuny/csi/csc330/threads/RunnableBufferWriter.java:import java.util.Date;
./src/test.java:import java.util.*;
Now I won't bother for explain the "\;" at the end of the command line - just do it ... it's a syntactical necessity. but the
-exec some-command {}
can be explained as follows: For every found file, "find" will call upon the specified command/program, substituting the "{}" notation with the found file path, e.g., ./src/test.java above.
So what's in the mygrep command? A short script that allows us to generate what grep would generate without the using "find -exec ...."
$ cat mygrep
file="$2"
pattern="$1"
result="$(grep "$pattern" $file)"
[[ -n "$result" ]] && echo "${file}: $result"
# execute grep and assign its output to a variable
# if grep found a match, and only if there's a match,
# display the file-name, followed by a colon,
# followed by the found pattern