[java] Java, List only subdirectories from a directory, not files

In Java, How do I list only subdirectories from a directory?

I'd like to use the java.io.File functionality, what is the best method in Java for doing this?

This question is related to java file

The answer is


The solution that worked for me, is missing from the list of answers. Hence I am posting this solution here:

File[]dirs = new File("/mypath/mydir/").listFiles((FileFilter)FileFilterUtils.directoryFileFilter());

Here I have used org.apache.commons.io.filefilter.FileFilterUtils from Apache commons-io-2.2.jar. Its documentation is available here: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html


Here is solution for my code. I just did a litlle change from first answer. This will list all folders only in desired directory line by line:

try {
            File file = new File("D:\\admir\\MyBookLibrary");
            String[] directories = file.list(new FilenameFilter() {
              @Override
              public boolean accept(File current, String name) {
                return new File(current, name).isDirectory();
              }
            });
            for(int i = 0;i < directories.length;i++) {
                if(directories[i] != null) {
                    System.out.println(Arrays.asList(directories[i]));

                }
            }
        }catch(Exception e) {
            System.err.println("Error!");
        }

You can use the JAVA 7 Files api

Path myDirectoryPath = Paths.get("path to my directory");
List<Path> subDirectories = Files.find(
                    myDirectoryPath ,
                    Integer.MAX_VALUE,
                    (filePath, fileAttr) -> fileAttr.isDirectory() && !filePath.equals(myDirectoryPath )
            ).collect(Collectors.toList());

If you want a specific value you can call map with the value you want before collecting the data.


A very simple Java 8 solution:

File[] directories = new File("/your/path/").listFiles(File::isDirectory);

It's equivalent to using a FileFilter (works with older Java as well):

File[] directories = new File("/your/path/").listFiles(new FileFilter() {
    @Override
    public boolean accept(File file) {
        return file.isDirectory();
    }
});

For those also interested in Java 7 and NIO, there is an alternative solution to @voo's answer above. We can use a try-with-resources that calls Files.find() and a lambda function that is used to filter the directories.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;


final Path directory = Paths.get("/path/to/folder");

try (Stream<Path> paths = Files.find(directory, Integer.MAX_VALUE, (path, attributes) -> attributes.isDirectory())) {
    paths.forEach(System.out::println);
} catch (IOException e) {
    ...
}

We can even filter directories by name by changing the lambda function:

(path, attributes) -> attributes.isDirectory() && path.toString().contains("test")

or by date:

final long now = System.currentTimeMillis();
final long yesterday = new Date(now - 24 * 60 * 60 * 1000L).getTime();

// modified in the last 24 hours
(path, attributes) -> attributes.isDirectory() && attributes.lastModifiedTime().toMillis() > yesterday

In case you're interested in a solution using Java 7 and NIO.2, it could go like this:

private static class DirectoriesFilter implements Filter<Path> {
    @Override
    public boolean accept(Path entry) throws IOException {
        return Files.isDirectory(entry);
    }
}

try (DirectoryStream<Path> ds = Files.newDirectoryStream(FileSystems.getDefault().getPath(root), new DirectoriesFilter())) {
        for (Path p : ds) {
            System.out.println(p.getFileName());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

@Mohamed Mansour you were almost there... the "dir" argument from that you were using is actually the curent path, so it will always return true. In order to see if the child is a subdirectory or not you need to test that child.

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));

Given a starting directory as a String

  1. Create a method that takes a String path as the parameter. In the method:
  2. Create a new File object based on the starting directory
  3. Get an array of files in the current directory using the listFiles method
  4. Loop over the array of files
    1. If it's a file, continue looping
    2. If it's a directory, print out the name and recurse on this new directory path

I'd like to use the java.io.File functionality,

In 2012 (date of the question) yes, not today. java.nio API has to be favored for such requirements.

Terrible with so many answers, but not the simple way that I would use that is Files.walk().filter().collect().

Globally two approaches are possible :

1)Files.walk(Path start, ) has no maxDepth limitations while

2)Files.walk(Path start, int maxDepth, FileVisitOption... options) allows to set it.

Without specifying any depth limitation, it would give :

Path directory = Paths.get("/foo/bar");

try {
    List<Path> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}

And if for legacy reasons, you need to get a List of File you can just add a map(Path::toFile) operation before the collect :

Path directory = Paths.get("/foo/bar");

try {
    List<File> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .map(Path::toFile)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}

This will literally list (that is, print) all subdirectories. It basically is a loop kind of where you don’t need to store the items in between to a list. This is what one most likely needs, so I leave it here.

Path directory = Paths.get("D:\\directory\\to\\list");

Files.walk(directory, 1).filter(entry -> !entry.equals(directory))
    .filter(Files::isDirectory).forEach(subdirectory ->
{
    // do whatever you want with the subdirectories
    System.out.println(subdirectory.getFileName());
});

    File files = new File("src");
    // src is folder name...
    //This will return the list of the subDirectories
    List<File> subDirectories = Arrays.stream(files.listFiles()).filter(File::isDirectory).collect(Collectors.toList());
// this will print all the sub directories
Arrays.stream(files.listFiles()).filter(File::isDirectory).forEach(System.out::println);

ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);