TL;DR: if you you need to filter out files/dirs by attributes - use Files.find(), if you don't need to filter by file attributes - use Files.walk().

Details

There is a slight difference which is actually explained in the documentation, but in a way that it feels completely wrong. Reading the source code makes it clear:

  • Files.find:

    return StreamSupport.stream(...)
                            .onClose(iterator::close)
                            .filter(entry -> matcher.test(entry.file(), entry.attributes()))
                            .map(entry -> entry.file());
    
  • Files.walk:

    return StreamSupport.stream(...)
                            .onClose(iterator::close)
                            .map(entry -> entry.file());
    

This means that if, in your eventual filter, you need to get and validate file attributes - chances are that File.find will be faster. That's because with File.walk, your filter callback will need an extra call to e.g. Files.readAttributes(file, BasicFileAttributes.class), while with File.find - the attributes are already retrieved and given to you in the filter callback.

I just tested it with my sample 10K-files-in-many-folders structure on Windows, by searching files only (i.e. excluding folders):

// pre-Java7/8 way via recursive listFiles (8037 files returned): 1521.657 msec.
for (File f : new File(dir).listFiles()) {
    if (f.isDirectory()) {
        _getFiles(files, path, pattern);
    } else {
        ...
    }
}

// Files.walk(8037 files returned): 1575.766823 msec.
try (Stream<Path> stream = Files.walk(path, Integer.MAX_VALUE) {
    files = stream.filter(p -> {
        if (Files.isDirectory(p)) { return false; } // this extra check makes it much slower than Files.find
        ... 
    }).map(p -> p.toString()).collect(Collectors.toList());
}

// Files.find(8037 files returned): 27.606675 msec.
try (Stream<Path> stream = Files.find(path, Integer.MAX_VALUE, (p, a) -> !a.isDirectory())) {
    files = stream.filter(p -> { ... }).map(p -> p.toString()).collect(Collectors.toList());
}

// Files.walkFileTree(8037 returned): 27.443974 msec.
Files.walkFileTree(new File(path).toPath(), new SimpleFileVisitor<Path>() { 
    @Override
    public FileVisitResult visitFile(Path p, BasicFileAttributes attrs) throws IOException {
        ...
        return FileVisitResult.CONTINUE;
    }
});
Answer from Borka on Stack Overflow
🌐
Mkyong
mkyong.com › home › java › java files.walk examples
Java Files.walk examples - Mkyong.com
December 2, 2020 - package com.mkyong.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 FilesWalkExample4 { public static void main(String[] args) throws IOException { Path path = Paths.get("C:\\test\\"); List<Path> paths = findByFileExtension(path, ".txt"); paths.forEach(x -> System.out.println(x)); } public static List<Path> findByFileExtension(Path path, String fileExtension) throws IOException { if (!Files.isDirectory(path)) { throw new IllegalArgumentException("Path must be a directory!"); } List<Path> result; try (Stream<Path> walk = Files.walk(path)) { result = walk .filter(Files::isRegularFile) // is a file .filter(p -> p.getFileName().toString().endsWith(fileExtension)) .collect(Collectors.toList()); } return result; } }
🌐
Medium
medium.com › @AlexanderObregon › javas-files-walk-method-explained-570d8a67247d
Java’s Files.walk() Method Explained | Medium
September 3, 2024 - Explore Java's Files.walk() method for efficient directory traversal, recursive processing, file filtering, and handling large file systems effectively.
Discussions

java - What is the difference between Files.walk.filter and Files.find? - Stack Overflow
This means that if, in your eventual filter, you need to get and validate file attributes - chances are that File.find will be faster. That's because with File.walk, your filter callback will need an extra call to e.g. More on stackoverflow.com
🌐 stackoverflow.com
Java Files.Walk to filter files only with starting with "O_" - Stack Overflow
Could you please help me how it is possible to filter only the files which is starting with "O_"? For me StartsWith and EndsWith methods didn't work.The result was always an empty list. Files.walk... More on stackoverflow.com
🌐 stackoverflow.com
python - Filtering os.walk() dirs and files - Stack Overflow
I'm looking for a way to include/exclude files patterns and exclude directories from a os.walk() call. Here's what I'm doing by now: import fnmatch import os includes = ['*.doc', '*.odt'] excludes... More on stackoverflow.com
🌐 stackoverflow.com
java - How to use Files.walk()... to get a graph of files based on conditions? - Stack Overflow
I have the following directory structures: /path/to/stuff/org/foo/bar/ /path/to/stuff/org/foo/bar/1.2.3/ /path/to/stuff/org/foo/bar/1.2.3/myfile.ext /path/to/stuff/org/foo/bar/1.2.4/ /path/to/stuf... More on stackoverflow.com
🌐 stackoverflow.com
May 22, 2017
🌐
ZetCode
zetcode.com › java › fileswalk
Java Files.walk - listing files in Java with Files.walk
July 7, 2024 - The program walks the directory for two levels. We apply a filter with Files.isRegular predicate.
Top answer
1 of 2
10

TL;DR: if you you need to filter out files/dirs by attributes - use Files.find(), if you don't need to filter by file attributes - use Files.walk().

Details

There is a slight difference which is actually explained in the documentation, but in a way that it feels completely wrong. Reading the source code makes it clear:

  • Files.find:

    return StreamSupport.stream(...)
                            .onClose(iterator::close)
                            .filter(entry -> matcher.test(entry.file(), entry.attributes()))
                            .map(entry -> entry.file());
    
  • Files.walk:

    return StreamSupport.stream(...)
                            .onClose(iterator::close)
                            .map(entry -> entry.file());
    

This means that if, in your eventual filter, you need to get and validate file attributes - chances are that File.find will be faster. That's because with File.walk, your filter callback will need an extra call to e.g. Files.readAttributes(file, BasicFileAttributes.class), while with File.find - the attributes are already retrieved and given to you in the filter callback.

I just tested it with my sample 10K-files-in-many-folders structure on Windows, by searching files only (i.e. excluding folders):

// pre-Java7/8 way via recursive listFiles (8037 files returned): 1521.657 msec.
for (File f : new File(dir).listFiles()) {
    if (f.isDirectory()) {
        _getFiles(files, path, pattern);
    } else {
        ...
    }
}

// Files.walk(8037 files returned): 1575.766823 msec.
try (Stream<Path> stream = Files.walk(path, Integer.MAX_VALUE) {
    files = stream.filter(p -> {
        if (Files.isDirectory(p)) { return false; } // this extra check makes it much slower than Files.find
        ... 
    }).map(p -> p.toString()).collect(Collectors.toList());
}

// Files.find(8037 files returned): 27.606675 msec.
try (Stream<Path> stream = Files.find(path, Integer.MAX_VALUE, (p, a) -> !a.isDirectory())) {
    files = stream.filter(p -> { ... }).map(p -> p.toString()).collect(Collectors.toList());
}

// Files.walkFileTree(8037 returned): 27.443974 msec.
Files.walkFileTree(new File(path).toPath(), new SimpleFileVisitor<Path>() { 
    @Override
    public FileVisitResult visitFile(Path p, BasicFileAttributes attrs) throws IOException {
        ...
        return FileVisitResult.CONTINUE;
    }
});
2 of 2
1

I believe walk() would be advantageous if you would need to apply some intermediary operation on the directory listing before applying a filter or parallelize the stream.

🌐
GitHub
gist.github.com › fredrikaverpil › 9761434
Walk folder and filter on filetype #python - Gist - GitHub
for root, dirs, files in os.walk( startDirectory ): for extension in ( tuple(filetypes) ): for filename in fnmatch.filter(files, extension): filepath = os.path.join(root, filename) print(os.path.join( filepath )) # do something ...` Sign up for free to join this conversation on GitHub.
🌐
Javaprogramto
javaprogramto.com › 2020 › 02 › java-8-files-walk.html
Java 8 Files walk() Examples JavaProgramTo.com
February 25, 2020 - package com.java.w3schools.blog.java8.files; 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 FilesWalkExample { public static void main(String[] args) { System.out.println("Files in folder : "); try (Stream<Path> filesWalk = Files.walk(Paths.get("."))) { List<String> result = filesWalk.filter(Files::isRegularFile).map(x -> x.toString()) .collect(Collectors.toList()); result.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } } } Output: In this program, We have used Files.walk() method and passed the src folder as an argument.
🌐
Program Creek
programcreek.com › java-api-examples
Java Code Examples for java.nio.file.Files#walk()
private Set<Path> toListOfPaths(DirectoryStream<Path> directoryStream) { Set<Path> directories = new HashSet<>(); for (Path p : directoryStream) { try (Stream<Path> paths = Files.walk(p)) { Set<Path> tree = paths.filter(Files::isDirectory) .collect(Collectors.toSet()); directories.addAll(tree); } catch (IOException ex) { LOG.errorf("Ignoring directory [{0}] - {1}", new Object[] { p.getFileName().toString(), ex.getMessage() }); } } return directories; } Example 4 ·
Find elsewhere
Top answer
1 of 8
65

This solution uses fnmatch.translate to convert glob patterns to regular expressions (it assumes the includes only is used for files):

import fnmatch
import os
import os.path
import re

includes = ['*.doc', '*.odt'] # for files only
excludes = ['/home/paulo-freitas/Documents'] # for dirs and files

# transform glob patterns to regular expressions
includes = r'|'.join([fnmatch.translate(x) for x in includes])
excludes = r'|'.join([fnmatch.translate(x) for x in excludes]) or r'$.'

for root, dirs, files in os.walk('/home/paulo-freitas'):

    # exclude dirs
    dirs[:] = [os.path.join(root, d) for d in dirs]
    dirs[:] = [d for d in dirs if not re.match(excludes, d)]

    # exclude/include files
    files = [os.path.join(root, f) for f in files]
    files = [f for f in files if not re.match(excludes, f)]
    files = [f for f in files if re.match(includes, f)]

    for fname in files:
        print fname
2 of 8
24

From docs.python.org:

os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])

When topdown is True, the caller can modify the dirnames list in-place … this can be used to prune the search …

for root, dirs, files in os.walk('/home/paulo-freitas', topdown=True):
    # excludes can be done with fnmatch.filter and complementary set,
    # but it's more annoying to read.
    dirs[:] = [d for d in dirs if d not in excludes] 
    for pat in includes:
        for f in fnmatch.filter(files, pat):
            print os.path.join(root, f)

I should point out that the above code assumes excludes is a pattern, not a full path. You would need to adjust the list comprehension to filter if os.path.join(root, d) not in excludes to match the OP case.

Top answer
1 of 3
42
Files.walk(Paths.get("/path/to/stuff/"))
     .filter(p -> p.toString().endsWith(".ext"))
     .map(p -> p.getParent().getParent())
     .distinct()
     .forEach(System.out::println);

This filters all files that have the extension and gets the parent path of their directory. distinct ensures that every path is used only once.

2 of 3
4

You are invoking the method printIfArtifactVersionDirectory for all visited directories. I did a little change to make it obvious:

static void printIfArtifactVersionDirectory(Path path) {
    System.out.println("--- " + path);
    ...
}

With that additional output you will get:

--- C:\Projects\stuff
--- C:\Projects\stuff\org
--- C:\Projects\stuff\org\foo
--- C:\Projects\stuff\org\foo\bar
--- C:\Projects\stuff\org\foo\bar\1.2.3
C:\Projects\stuff\org\foo\bar
--- C:\Projects\stuff\org\foo\bar\1.2.4
C:\Projects\stuff\org\foo\bar
--- C:\Projects\stuff\org\foo\bar\blah
--- C:\Projects\stuff\org\foo\bar\blah\2.1
C:\Projects\stuff\org\foo\bar\blah
--- C:\Projects\stuff\org\foo\bar\blah\2.2
C:\Projects\stuff\org\foo\bar\blah

So you get the output as often as you have artifact version directories. If you want to remember that you already did the output for one directory, you must make store this information somewhere. One quick implementation could be:

static class Foo {
    private static final Set<Path> visited = new HashSet<>();

    static void printIfArtifactVersionDirectory(Path path) {
        ...
        Path parent = path.getParent();
        if (!filePaths.isEmpty() && !visited.contains(parent)) {
            visited.add(parent);
            System.out.println(parent);
        }
    }
}

With this you get the expected output:

C:\Projects\stuff\org\foo\bar
C:\Projects\stuff\org\foo\bar\blah

A better solution would be to use the set for storing the visited parents and only print them after visiting them all:

static class PathStore {
    private final Set<Path> store = new HashSet<>();

    void visit(Path path) {
        File f = path.toAbsolutePath().toFile();
        List<String> filePaths = Arrays.asList(f.list(new MyExtFilenameFilter()));
        if (!filePaths.isEmpty()) {
            store.add(path.getParent());
        }
    }

    void print() {
        store.forEach(System.out::println);
    }
}

Usage:

PathStore pathStore = new PathStore();
Files.walk(Paths.get("/path/to/stuff/"))
        .filter(Files::isDirectory)
        .forEach(pathStore::visit);
pathStore.print();
🌐
GitHub
github.com › kmalakoff › walk-filtered
GitHub - kmalakoff/walk-filtered: A simple, performant file system walker to provided fine-grained control over directories and files to walk. · GitHub
A simple, performant file system walker to provided fine-grained control over directories and files to walk. Supports Node 0.10 and above. Note: This API is very robust for a variety of use cases as it passes the chokidar and readdirp test suites ...
Author   kmalakoff
🌐
Reddit
reddit.com › r/learnjava › efficient processing without multiple files walk
r/learnjava on Reddit: Efficient processing without multiple Files walk
April 22, 2023 -

I am writing a simple program that walks the file tree to generate various statistics about the files.

For example:

try (Stream<Path> walk = Files.walk(PATH)) {
    // Find all directories
    List<Path> dirs = walk.filter(Files::isDirectory).collect(Collectors.toList());

    // Find all files
    List<Path> files = walk.filter(Files::isRegularFile).collect(Collectors.toList());

    // Find zip archive files
    List<Path> zips = walk.filter(
        p -> p.getFileName().toString().toLowerCase().endsWith(".zip"))
        .collect(Collectors.toList());

    // Find files bigger than 1 Mb
    List<Path> filesBiggerThan1Mb = walk.filter(p -> {
        try {
            return Files.size(p) > 1048576;
        } catch (IOException e) {					
            e.printStackTrace();
            return false;
        }
    }).collect(Collectors.toList());

    // Get total size of all files
    long totalSize = walk.filter(Files::isRegularFile).mapToLong(p -> {
        try {
            return Files.size(p);
        } catch (IOException e) {
            e.printStackTrace();
            return 0;
        }
    }).sum();
}

Currently it walks the file tree multiple times by reusing the walk object. Although it seems like either the JRE or os does some caching in memory, and subsequent Files walks are much faster, I am wondering how I can write it in a different way to only need to invoke Files walk only once and do everything in 1 sweep.

🌐
Mkyong
mkyong.com › home › files.walk
Files.walk Archives - Mkyong.com %
This article shows how to Java 8 Files.walk to walk a file tree and stream operation filter to find files that match a specific file extension from a folder and its subfolders.
🌐
YouTube
youtube.com › watch
How to Use Files.walk in Java with a Filter for Specific File Names - YouTube
Learn how to filter files while using `Files.walk` in Java by checking against a provided list of file names. This guide offers a clear step-by-step solution...
Published   September 15, 2025
Views   1
🌐
Javastudyguide
ocpj8.javastudyguide.com › ch25.html
Java 8 Programmer II Study Guide: Exam 1Z0-809
This method is similar to Files.walk(), but takes an additional argument of type BiPredicate that is used to filter the files and directories.
🌐
Tabnine
tabnine.com › home › code library
Code Library - Tabnine
July 25, 2024 - Get the answers and suggestions you need from our AI code assistant. Get started in minutes with a free 90 day trial of Tabnine Pro.
🌐
YouTube
youtube.com › luke chaffey
What is the difference between Files.walk.filter and Files.find? - YouTube
java: What is the difference between Files.walk.filter and Files.find?Thanks for taking the time to learn more. In this video I'll go through your question, ...
Published   June 8, 2023
Views   27
🌐
pythontutorials
pythontutorials.net › blog › filtering-os-walk-dirs-and-files
Python os.walk() Filtering: How to Include/Exclude Files and Directories Effectively — pythontutorials.net
However, by default, os.walk() traverses all directories and lists all files, which can be inefficient or irrelevant for specific use cases (e.g., ignoring log files, excluding hidden directories, or targeting only .py files). Effective filtering—including or excluding specific files and directories—turns os.walk() from a blunt tool into a precision instrument.