Java SimpleFileVisitor
last modified August 22, 2026
In this article we learn how to use SimpleFileVisitor to walk a
file tree in Java. We visit directories and files, search for matching paths,
handle traversal errors, and delete a directory tree.
SimpleFileVisitor is an adapter class from the
java.nio.file package. It implements the
FileVisitor<Path> interface with default implementations for
all visitor methods. We override only the callbacks that our operation needs.
The examples use Java 25's compact source-file syntax. With an earlier Java
version, place the code inside a class and use a conventional
public static void main(String[] args) method.
Walking a file tree
The Files.walkFileTree method starts at a given path and invokes a
visitor during the traversal. The two-argument overload walks the complete
tree using the default options.
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
void main() throws IOException {
var root = Path.of(".");
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
});
}
The visitor prints every file below the current directory. Directories are
visited as well, but they are not printed because this example overrides only
visitFile.
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
});
The walkFileTree method receives the starting path and a visitor.
For every regular file, it calls visitFile with the path and its
BasicFileAttributes. Returning CONTINUE tells the
traversal to keep going.
Visitor methods
The FileVisitor interface defines four callbacks. The
SimpleFileVisitor implementation supplies default behavior, so we
can override only the callbacks relevant to our task.
preVisitDirectoryis called before the entries in a directory are visited.visitFileis called when a file is visited.visitFileFailedis called when a file cannot be visited.postVisitDirectoryis called after all entries in a directory have been visited.
The callbacks return a FileVisitResult. The result controls what
happens next:
CONTINUEcontinues the traversal.SKIP_SUBTREEskips the remaining entries in the current directory.SKIP_SIBLINGSskips the remaining entries in the current directory and continues with the parent directory.TERMINATEstops the traversal immediately.
Limiting the traversal
The overload with four arguments accepts traversal options and a maximum
depth. A depth of 0 visits only the starting path. A depth of
1 also visits entries directly below it.
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Set;
void main() throws IOException {
var root = Path.of(".");
var options = Set.<FileVisitOption>of();
Files.walkFileTree(root, options, 2, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
});
}
This example visits the starting directory and its children to a maximum depth of two. The empty option set means that symbolic links are not followed.
Finding files
The visitor can inspect each path and stop the traversal when it finds a match. In the following example, we print Java source files and continue walking the tree.
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
void main() throws IOException {
var root = Path.of(".");
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
var name = file.getFileName().toString();
if (name.endsWith(".java")) {
System.out.println(file);
}
return FileVisitResult.CONTINUE;
}
});
}
The getFileName method returns the final component of the path.
We compare its text with endsWith and ignore all other files.
Skipping directories
We can prevent a directory and all of its children from being visited by
returning SKIP_SUBTREE from preVisitDirectory.
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
void main() throws IOException {
var root = Path.of(".");
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) {
if (dir.getFileName() != null
&& dir.getFileName().toString().equals(".git")) {
return FileVisitResult.SKIP_SUBTREE;
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
});
}
When the visitor reaches a directory named .git, it skips that
directory and everything below it. The traversal then continues with the next
entry in the parent directory.
Handling visit failures
Permission problems, broken links, and other I/O errors can prevent a path
from being visited. Override visitFileFailed when the application
should report the problem and continue with other paths.
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
void main() throws IOException {
var root = Path.of(".");
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
System.err.println("Could not visit " + file + ": " + exc.getMessage());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
});
}
Returning CONTINUE ignores the failure for traversal purposes; it
does not repair the underlying permission or I/O problem. If a failed visit
must abort the operation, rethrow the exception or return
TERMINATE according to the application's error policy.
Deleting a directory tree
Deleting files is a common use of SimpleFileVisitor. Files must be
deleted before their containing directories, so we delete files in
visitFile and directories in postVisitDirectory.
This example is destructive. Confirm the root path before running it and use a test directory first.
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
void main() throws IOException {
var root = Path.of("temporary-directory");
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
if (exc != null) {
throw exc;
}
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
The postVisitDirectory callback runs after the directory's
contents have been processed. This order allows the directory to be removed
only after all of its files and child directories have been deleted.
Following symbolic links
By default, walkFileTree does not follow symbolic links. To follow
them, pass FileVisitOption.FOLLOW_LINKS in the option set.
Following links can cause a cycle or make the traversal leave the intended
directory, so use the option only when it is required.
import java.nio.file.FileVisitOption; import java.util.Set; var options = Set.of(FileVisitOption.FOLLOW_LINKS);
When following links, the traversal can throw a
FileSystemLoopException if it detects a cycle. Code that follows
links should also consider permissions, mount points, and the possibility that
the same file is reachable through more than one path.
Source
Java SimpleFileVisitor - language reference
Files.walkFileTree - language reference
Author
List all Java tutorials.