The Files.find
API is available since Java 8. It searches or finds files from a file tree quickly.
In the old days, we always use an error-prone recursive loop to walk a file tree. This Java 8 Files.find
can save you a lot of time.
1. Files.find() Signature
Review the Files.find()
signature.
Files.java
public static Stream<Path> find(Path start, int maxDepth, BiPredicate<Path, BasicFileAttributes> matcher, FileVisitOption... options) throws IOException
- The
path
, starting file or folder. - The
maxDepth
defined the maximum number of directory levels to search. If we put1
, which means the search for top-level or root folder only, ignore all its subfolders; If we want to search for all folder levels, putInteger.MAX_VALUE
. - The
BiPredicate<Path, BasicFileAttributes>
is for condition checking or filtering. - The
FileVisitOption
tells if we want to follow symbolic links, default is no. We can putFileVisitOption.FOLLOW_LINKS
to follow symbolic links.
2. Find files by filename
This example uses Files.find()
to find files that matched filename google.png
, starting from the folder C:\\test
, and included all levels of its subfolders.
FileFindExample1.java
package com.favtuts.io.api; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class FileFindExample1 { public static void main(String[] args) throws IOException { Path path = Paths.get("C:\\test"); List<Path> result = findByFileName(path, "google.png"); result.forEach(x -> System.out.println(x)); } public static List<Path> findByFileName(Path path, String fileName) throws IOException { List<Path> result; try (Stream<Path> pathStream = Files.find(path, Integer.MAX_VALUE, (p, basicFileAttributes) -> p.getFileName().toString().equalsIgnoreCase(fileName)) ) { result = pathStream.collect(Collectors.toList()); } return result; } }
We also can use Files
APIs to check the path further.
FileFindExample1.java
try (Stream<Path> pathStream = Files.find(path, Integer.MAX_VALUE, (p, basicFileAttributes) ->{ // if directory or no-read permission, ignore if(Files.isDirectory(p) || !Files.isReadable(p)){ return false; } return p.getFileName().toString().equalsIgnoreCase(fileName); }) )
3. Find files by file size
This example uses Files.find()
to find files containing file size greater or equals 100MB.
FileFindExample2.java
package com.favtuts.io.api; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class FileFindExample2 { public static void main(String[] args) throws IOException { Path path = Paths.get("C:\\Users\\favtuts\\Downloads"); long fileSize = 1024 * 1024 * 100; // 100M List<Path> result = findByFileSize(path, fileSize); for (Path p : result) { System.out.println(String.format("%-40s [fileSize]: %,d", p, Files.size(p))); } } public static List<Path> findByFileSize(Path path, long fileSize) throws IOException { List<Path> result; try (Stream<Path> pathStream = Files.find(path, Integer.MAX_VALUE, (p, basicFileAttributes) -> { try { if (Files.isDirectory(p)) { // ignore directory return false; } return Files.size(p) >= fileSize; } catch (IOException e) { System.err.println("Unable to get the file size of path : " + path); } return false; } )) { result = pathStream.collect(Collectors.toList()); } return result; } }
Output samples.
C:\Users\favtuts\Downloads\hello.mp4 [fileSize]: 4,796,543,886
C:\Users\favtuts\Downloads\java.mp4.bk [fileSize]: 5,502,785,778
C:\Users\favtuts\Downloads\ubuntu-20.04.1-desktop-amd64.iso [fileSize]: 2,785,017,856
#...
4. Find files by last modified time
This example uses File.find()
to find files containing last modified time equals or after yesterday.
FileFindExample3.java
package com.favtuts.io.api; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class FileFindExample3 { private static DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); public static void main(String[] args) throws IOException { // find files, LastModifiedTime from yesterday and above List<Path> result = findByLastModifiedTime( Paths.get("C:\\test"), Instant.now().minus(1, ChronoUnit.DAYS)); for (Path p : result) { // formatting... BasicFileAttributes attrs = Files.readAttributes(p, BasicFileAttributes.class); FileTime time = attrs.lastModifiedTime(); LocalDateTime localDateTime = time.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDateTime(); System.out.println(String.format("%-40s [%s]", p, localDateTime.format(DATE_FORMATTER))); } } public static List<Path> findByLastModifiedTime(Path path, Instant instant) throws IOException { List<Path> result; try (Stream<Path> pathStream = Files.find(path, Integer.MAX_VALUE, (p, basicFileAttributes) -> { if(Files.isDirectory(p) || !Files.isReadable(p)){ return false; } FileTime fileTime = basicFileAttributes.lastModifiedTime(); // negative if less, positive if greater // 1 means fileTime equals or after the provided instant argument // -1 means fileTime before the provided instant argument int i = fileTime.toInstant().compareTo(instant); return i > 0; } )) { result = pathStream.collect(Collectors.toList()); } return result; } }
Output samples and assume today is 02/12/2020
C:\test\a.txt [02/12/2020 13:01:20]
C:\test\b.txt [01/12/2020 12:11:21]
#...
Download Source Code
$ git clone https://github.com/favtuts/java-core-tutorials-examples
$ cd java-io