Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List only folders of certain depth using Java 8 streams

Considering there is the "new" streams API in Java 8 I can use Files.walk to iterate over a folder. How can I only get the child folders of my given directory if using this method or maybe depth=2?

I currently have this working example, which sadly also prints the root path as all "subfolders".

Files.walk(Paths.get("/path/to/stuff/"))
     .forEach(f -> {
        if (Files.isDirectory(f)) {
            System.out.println(f.getName());
        }
     });

I therefore reverted to the following approach. Which stores the folders in memory and needs handling of the stored list afterwards, which I would avoid and use lambdas instead.

File[] directories = new File("/your/path/").listFiles(File::isDirectory);
like image 880
lony Avatar asked Jul 26 '18 06:07

lony


4 Answers

Here is a solution that works with arbitrary minDepth and maxDepth also larger than 1. Assuming minDepth >= 0 and minDepth <= maxDepth:

final int minDepth = 2;
final int maxDepth = 3;
final Path rootPath = Paths.get("/path/to/stuff/");
final int rootPathDepth = rootPath.getNameCount();
Files.walk(rootPath, maxDepth)
        .filter(e -> e.toFile().isDirectory())
        .filter(e -> e.getNameCount() - rootPathDepth >= minDepth)
        .forEach(System.out::println);

To accomplish what you asked originally in the question of listing "...only folders of certain depth...", just make sure minDepth == maxDepth.

like image 81
L. Holanda Avatar answered Nov 09 '22 20:11

L. Holanda


You can make use of the second overload of the Files#walk method to set the max depth explicitly. Skip the first element of the stream to ignore the root path, then you can filter only directories to finally print each one of them.

final Path root = Paths.get("<your root path here>");

final int maxDepth = <your max depth here>;

Files.walk(root, maxDepth)
    .skip(1)
    .filter(Files::isDirectory)
    .map(Path::getFileName)
    .forEach(System.out::println);
like image 28
marsouf Avatar answered Nov 09 '22 20:11

marsouf


To list only sub-directories of a given directory:

Path dir = Paths.get("/path/to/stuff/");
Files.walk(dir, 1)
     .filter(p -> Files.isDirectory(p) && ! p.equals(dir))
     .forEach(p -> System.out.println(p.getFileName()));
like image 16
Andreas Avatar answered Nov 09 '22 21:11

Andreas


public List<String> listFilesInDirectory(String dir, int depth) throws IOException {
    try (Stream<Path> stream = Files.walk(Paths.get(dir), depth)) {
        return stream
                .filter(file -> !Files.isDirectory(file))
                .map(Path::getFileName)
                .map(Path::toString)
                .collect(Collectors.toList());
    }
}
like image 2
ghandour abdelkrim Avatar answered Nov 09 '22 21:11

ghandour abdelkrim