Memra

Directory traversal with Files.list and Files.walk

Listing directory contents and walking file trees — both return a Stream that must be closed.

Walking the file tree

Files.list(dir) returns a Stream<Path> of the direct children of a directory (not recursive):

try (Stream<Path> entries = Files.list(Path.of("src"))) {
    entries.filter(Files::isRegularFile)
           .forEach(System.out::println);
}

Files.walk(dir) walks recursively — every file and directory in the subtree:

try (Stream<Path> all = Files.walk(Path.of("."), 3)) {  // max depth 3
    all.filter(p -> p.toString().endsWith(".java"))
       .forEach(System.out::println);
}

The second argument is the max depth (optional — omit it to walk the entire tree).

Closing is mandatory. Both Files.list and Files.walk hold open a directory handle. Forgetting to close leaks the handle. Always use try-with-resources.

Files.newDirectoryStream is an alternative that produces an Iterable<Path> instead of a stream — useful in a for-each loop:

try (DirectoryStream<Path> ds =
        Files.newDirectoryStream(Path.of("."), "*.{java,class}")) {
    for (Path p : ds) System.out.println(p);
}

The glob pattern "*.{java,class}" uses PathMatcher syntax — simpler than a predicate when you just need to filter by extension.

NORMAL ~/memra/learn/java-from-zero/directory-traversal utf-8 LF