lony
lony

Reputation: 7770

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);

Upvotes: 15

Views: 10768

Answers (6)

ghandour abdelkrim
ghandour abdelkrim

Reputation: 41

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());
    }
}

Upvotes: 2

L. Holanda
L. Holanda

Reputation: 4631

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.

Upvotes: 18

marsouf
marsouf

Reputation: 1147

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);

Upvotes: 7

kira
kira

Reputation: 15

Agree with Andreas‘s answer,u can also use Files.list instead of Files.walk

Files.list(Paths.get("/path/to/stuff/"))
.filter(p -> Files.isDirectory(p) && ! p.equals(dir))
.forEach(p -> System.out.println(p.getFileName()));

Upvotes: 0

GolamMazid Sajib
GolamMazid Sajib

Reputation: 9437

You can also try with this:

private File getSubdirectory(File file){
    try {
        return new File(file.getAbsolutePath().substring(file.getParent().length()));
    }catch (Exception ex){

    }
    return null;
}

collect file:

File[] directories = Arrays.stream(new File("/path/to/stuff")
          .listFiles(File::isDirectory)).map(Main::getSubdirectory)
                                        .toArray(File[]::new);

Upvotes: 0

Andreas
Andreas

Reputation: 159096

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()));

Upvotes: 17

Related Questions