137. Searching for files/folders in a file tree

Searching for files or folders in a file tree is a common task that's needed in a lot of situations. Thanks to JDK 8 and the new Files.find() method, we can accomplish this pretty easily.

The Files.find() method returns a Stream<Path> which is lazily populated with the paths that match the provided finding constraints:

public static Stream<Path> find​(
Path start,
int maxDepth,
BiPredicate<Path, ​BasicFileAttributes > matcher,
FileVisitOption...options
) throws IOException

This method acts as the walk() method, and so it traverses the current file tree, starting from the given path (start), and reaching the maximum given depth (maxDepth). During the iteration of the current file tree, this method applies the given predicate (matcher). Via this predicate, we specify the constraints that must be matched by each file that goes in the final stream. Optionally, we can specify a set of visiting options (options).

Path startPath = Paths.get("D:/learning");

Let's take a look at some examples that are meant to clarify the usage of this method:

  • Find all the files ending with the .properties extension and follow the symbolic links:
Stream<Path> resultAsStream = Files.find(
startPath,
Integer.MAX_VALUE,
(path, attr) -> path.toString().endsWith(".properties"),
FileVisitOption.FOLLOW_LINKS
);
  • Find all the regular files whose names start with application:
Stream<Path> resultAsStream = Files.find(
startPath,
Integer.MAX_VALUE,
(path, attr) -> attr.isRegularFile() &amp;&amp;
path.getFileName().toString().startsWith("application")
);
  • Find all the directories that were created after 16 March 2019:
Stream<Path> resultAsStream = Files.find(
startPath,
Integer.MAX_VALUE,
(path, attr) -> attr.isDirectory() &amp;&amp;
attr.creationTime().toInstant()
.isAfter(LocalDate.of(2019, 3, 16).atStartOfDay()
.toInstant(ZoneOffset.UTC))
);

If we prefer to express the constraints as an expression (for example, a regular expression), then we can use the PathMatcher interface. This interface comes with a method called matches(Path path), which can tell if the given path matches this matcher's pattern.

A FileSystem implementation supports the glob and regex syntaxes (and may support others) via FileSystem.getPathMatcher(String syntaxPattern). The constraints take the form of syntax:pattern.

Based on PathMatcher, we can write helper methods that are capable of covering a wide range of constraints. For example, the following helper method only fetches files that respect the given constraint as a syntax:pattern:

public static Stream<Path> fetchFilesMatching(Path root,
String syntaxPattern) throws IOException {

final PathMatcher matcher
= root.getFileSystem().getPathMatcher(syntaxPattern);

return Files.find(root, Integer.MAX_VALUE, (path, attr)
-> matcher.matches(path) &amp;&amp; !attr.isDirectory());
}

Finding all Java files via the glob syntax can be achieved as follows:

Stream<Path> resultAsStream 
= fetchFilesMatching(startPath, "glob:**/*.java");

If all we want to do is list the files from the current folder (without any constraints and a single level deep), then we can rely on the Files.list() method, as shown in the following example:

try (Stream<Path> allfiles = Files.list(startPath)) {
...
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.119.106