List files matching a naming pattern in Java
This tutorial shows how to recursively list files matching a naming pattern in Java.
To be able to list the files, you should be able to walk the file tree. JDK 7 provides a FileVisitor interface to walk a file tree. The FileVisitor type is given callbacks at key points in the traversal process. The FileVisitor interface defines the following four methods corresponding to the situation in the traversal:
- preVisitDirectory – Invoked before a directory’s entries are visited.
- postVisitDirectory – Invoked after all the entries in a directory are visited. If any errors are encountered, the specific exception is passed to the method.
- visitFile – Invoked on the file being visited. The file’s BasicFileAttributes is passed to the method
- visitFileFailed – Invoked when the file cannot be accessed. The specific exception is passed to the method. You can choose whether to throw the exception, print it to the console or a log file, and so on.
One needs to implement the FileVisitor interface and implement all the callback methods. The tree traversal logic is implemented by Files.walkFileTree which takes a FileVisitor type as an input and calls the appropriate FileVisitor interface methods during the traversal.
JDK also provides a default implementation of the FileVisitor interface in SimpleFileVisitor class. Instead of implementing all the FileVisitor methods you can as well extend the SimpleFileVisitor class and override only the methods you are interested in.
For the sake of this tutorial we will extend the SimpleFileVisitor class and implement a simple utility class FileFinder which accepts a wildcard naming pattern and records the all the files that match the pattern during the file tree traversal.
FileFinder Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
package com.wilddiary.utils; import static java.nio.file.FileVisitResult.CONTINUE; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class FileFinder extends SimpleFileVisitor<Path> { private final PathMatcher matcher; private List<Path> matchedPaths = new ArrayList<Path>(); FileFinder(String pattern) { matcher = FileSystems.getDefault() .getPathMatcher("glob:" + pattern); } // Compares the glob pattern against // the file or directory name. void match(Path file) { Path name = file.getFileName(); if (name != null && matcher.matches(name)) { matchedPaths.add(name); } } // Invoke the pattern matching // method on each file. @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { match(file); return CONTINUE; } // Invoke the pattern matching // method on each directory. @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { match(dir); return CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) { System.err.println(exc); return CONTINUE; } public int getTotalMatches() { return matchedPaths.size(); } public Collection<Path> getMatchedPaths() { return matchedPaths; } } // class FileFinder ends |
Usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; public class FileFinderDemo { public static void main(String[] args) throws IOException { // create a FileFinder instance with a naming pattern FileFinder finder = new FileFinder("*.png"); // pass the initial directory and the finder to the file tree walker Files.walkFileTree(Paths.get("/Users/userXYZ/icons"), finder); // get the matched paths Collection<Path> matchedFiles = finder.getMatchedPaths(); // print the matched paths for (Path path : matchedFiles) { System.out.println(path.getFileName()); } } } |
The usage is pretty simple. First, we create an instance of the FileFinder class by passing in the naming pattern. Then, we pass the instance to Files.walkFileTree that give callbacks to our FileFinder instance as it walks the file tree. Our FileFinder instance matches the pattern with every file and directory path that is encountered and records those that match. Files.walkFileTree returns once the traversal is complete. Then you can call getMatchedPaths() on the FileFinder instance that returns a collection of all the paths matching the input naming pattern.
Sample Output
1 2 3 4 5 6 7 8 9 10 11 12 |
home.png apis.png canvas1.png help1.png rectangle.png run.png service.png start.png support.png zoom-in-16.png zoom-in-xxl.png zoom-out-16.png |
What is CONTINUE in the import:
import static java.nio.file.FileVisitResult.CONTINUE;