Writing find with Java 8 streams
23 Jul 2015Intro
In this guide, we’re going to write our very own simplified find
command using Java 8 streams. By the end we will be able to run it from the command line, just like the unix find program.
Pre-reqs
This post assumes you at least a little familiar with Java 8 streams and regular expressions. We’re actually going to review find
, so it’s ok if you do not yet know it.
What is find?
According to wikipedia, “find is a command-line utility that searches through one or more directory trees of a file system, locates files based on some user-specified criteria and applies a user-specified action on each matched file.”
So if we wanted to find all the markdown files in the kahlil.me directory, we could run:
find . -name "\*.md"
and we would get as a result:
./posts/2015-07-18-hello-world.md
./posts/2015-07-18-java-8-stream-sql.md
./posts/2015-07-21-java-8-find-and-grep-with-streams.md
./about.md
./archive.md
./LICENSE.md
./README.md
To keep things simple, our find
won’t be able to perform any user-specified actions on the files it finds. Instead, it will simply take a starting directory and a pattern, then print out the full paths of any files that match the pattern and are somewhere in that directory.
Find implementation
find
method
This is where all of our find logic resides. It turns out to be pretty straightforward.
We’re going to use java.nio.Files::walk
to recursively traverse all subdirectories of the starting directory we pass it. Then, we’re going to filter the results and only keep the files that match the pattern we passed.
(note: I’ve omitted the throws clause to keep the code clean).
public static Stream<Path> find(String dir, String pattern) {
return Files.walk(Paths.get(dir))
.filter(path -> path.getFileName()
.toString()
.matches(pattern));
}
main
method
All we need to do in our main method is pass the command line arguments to find
, and print the results.
public static void main(String[] args) throws IOException {
find(args[0], args[1]).forEach(System.out::println);
}
Running find
Let’s use Find.java to find all css files that style this very website.
java Find ~/dev/projects/kahliloppenheimer.github.io ".*\.css"
/Users/kahliloppenheimer/dev/projects/kahliloppenheimer.github.io/_site/assets/css/browser-support.css
/Users/kahliloppenheimer/dev/projects/kahliloppenheimer.github.io/_site/assets/css/main.css