简体   繁体   English

Java,仅列出目录中的子目录,而不是文件

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

In Java, How do I list only subdirectories from a directory?在 Java 中,如何仅列出目录中的子目录?

I'd like to use the java.io.File functionality, what is the best method in Java for doing this?我想使用 java.io.File 功能,Java 中执行此操作的最佳方法是什么?

You can use the File class to list the directories.您可以使用File类列出目录。

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

Update更新

Comment from the author on this post wanted a faster way, great discussion here: How to retrieve a list of directories QUICKLY in Java?作者对这篇文章的评论想要一种更快的方法,这里有很好的讨论: 如何在 Java 中快速检索目录列表?

Basically:基本上:

  1. If you control the file structure, I would try to avoid getting into that situation.如果您控制文件结构,我会尽量避免陷入这种情况。
  2. In Java NIO.2, you can use the directories function to return an iterator to allow for greater scaling.在 Java NIO.2 中,您可以使用目录函数返回迭代器以实现更大的扩展。 The directory stream class is an object that you can use to iterate over the entries in a directory.目录流类是一个对象,可用于迭代目录中的条目。

A very simple Java 8 solution:一个非常简单的 Java 8 解决方案:

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

It's equivalent to using a FileFilter (works with older Java as well):它相当于使用 FileFilter(也适用于较旧的 Java):

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

@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. @Mohamed Mansour 你快到了......你使用的“dir”参数实际上是当前路径,所以它总是会返回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));

In case you're interested in a solution using Java 7 and NIO.2, it could go like this:如果您对使用 Java 7 和 NIO.2 的解决方案感兴趣,它可以是这样的:

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();
    }
ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);

For those also interested in Java 7 and NIO, there is an alternative solution to @voo's answer above .对于那些也对 Java 7 和 NIO 感兴趣的人,上面@voo 的回答有一个替代解决方案。 We can use a try-with-resources that calls Files.find() and a lambda function that is used to filter the directories.我们可以使用调用Files.find()try-with-resources和用于过滤目录的 lambda 函数。

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:我们甚至可以通过更改 lambda 函数按名称过滤目录:

(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

I'd like to use the java.io.File functionality,我想使用 java.io.File 功能,

In 2012 (date of the question) yes, not today. 2012 年(问题的日期)是的,不是今天。 java.nio API has to be favored for such requirements. java.nio API 必须满足这样的需求。

Terrible with so many answers, but not the simple way that I would use that is Files.walk().filter().collect() .有这么多答案很糟糕,但不是我使用的简单方法Files.walk().filter().collect()

Globally two approaches are possible :在全球范围内,可能有两种方法:

1) Files.walk(Path start, ) has no maxDepth limitations while 1) Files.walk(Path start, )没有maxDepth限制,而

2) Files.walk(Path start, int maxDepth, FileVisitOption... options) allows to set it. 2) Files.walk(Path start, int maxDepth, FileVisitOption... options)允许设置它。

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 :如果由于遗留原因,您需要获取一个File列表,您可以在 collect 之前添加一个map(Path::toFile)操作:

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
}

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.这里我使用了 Apache commons-io-2.2.jar 中的org.apache.commons.io.filefilter.FileFilterUtils Its documentation is available here: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html其文档可在此处获得: https : //commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html

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

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

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!");
        }

Given a starting directory as a String给定一个起始目录作为String

  1. Create a method that takes a String path as the parameter.创建一个将String路径作为参数的方法。 In the method:在方法中:
  2. Create a new File object based on the starting directory根据起始目录创建一个新的File对象
  3. Get an array of files in the current directory using the listFiles method使用listFiles方法获取当前目录中的文件数组
  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如果是目录,则打印出名称并在此新目录路径上递归

You can use the JAVA 7 Files api您可以使用 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.如果你想要一个特定的值,你可以在收集数据之前用你想要的值调用 map。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM