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


Answers:


141

您可以使用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));

更新资料

作者对这篇文章的评论希望有一个更快的方法,在这里进行了精彩的讨论: 如何用Java快速检索目录列表?

基本上:

  1. 如果您控制文件结构,我将尽量避免陷入这种情况。
  2. 在Java NIO.2中,可以使用directorys函数返回一个迭代器,以实现更大的缩放比例。目录流类是一个对象,可用于遍历目录中的条目。

您好,感谢您的回复。但我不必遍历目录中的所有项目。我必须直接从目录中列出子目录。B'coz我有很多文件,并且目录中只有几个子目录,因此检查isDirectory()很耗时。请以其他方式回复我。
Lokesh Paunikar,2011年

我更新了我的文章,特别是看看Jon Skeet对这个问题的评论。自Java NIO 2以来,NIO响应都有一个针对目录函数的迭代器,该迭代器返回目录流。
穆罕默德·曼苏尔

您指的是什么Skeet评论?在这里表现更好的答案是什么?
Stealth Rabbi 2015年

107

一个非常简单的Java 8解决方案:

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

等效于使用FileFilter(也适用于较旧的Java):

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

4
双冒号::在这种情况下如何工作?
snickers10m 2015年

我注意到没有其他答案使用FileFilter,所以我添加了等效版本而不使用方法引用。有关方法引用的更多信息,请参考此SO问题本文
headsvk 2015年

这会得到子目录还是直接在/ your / path /下的目录?
amadain


14

@Mohamed Mansour,您快要在那里了……您所使用的“ dir”参数实际上是当前路径,因此它将始终返回true。为了查看该子目录是否是子目录,您需要测试该子目录。

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

7

如果您对使用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();
    }

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

嗨,欢迎来到StackOverflow!您能否详细说明您的答案?像解释代码片段中有趣的部分,还是链接到文档以供进一步阅读?
Richard-Degenne

这应该是正确的答案,因为它为File对象提供了完整的Canonical Path。这可能是旧的,但它是值得指出这一点
杰罗敦格

2

对于也对Java 7和NIO感兴趣的用户,可以使用上述@voo答案的替代解决方案。我们可以使用调用的try-with-resourcesFiles.find()和用于过滤目录的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) {
    ...
}

我们甚至可以通过更改lambda函数来按名称过滤目录:

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

或按日期:

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

2

我想使用java.io.File功能,

是的,在2012年(问题的日期),今天不是。 java.nio对于此类要求,必须优先使用API​​。

有这么多答案很糟糕,但是我使用的简单方法不是Files.walk().filter().collect()

在全球范围内,两种方法都是可行的:

1)Files.walk(Path start, )没有maxDepth限制,而

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

不指定任何深度限制,它将给出:

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

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

如果由于遗留原因,您需要获取List,File可以map(Path::toFile)在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
}

Files.list(Path)可能与相同Files.walk(Path,1)
David L.

Files.list(Path)如果我们不想递归地迭代文件夹,@ David L确实是一个不错的选择。以递归方式迭代文件夹,比较walk()合适。
davidxxx

1

答案列表中缺少对我有用的解决方案。因此,我在这里发布此解决方案:

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

在这里,我使用了org.apache.commons.io.filefilter.FileFilterUtils来自Apache commons-io-2.2.jar的文件。可在以下位置获取其文档:https : //commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html


0

给定一个起始目录 String

  1. 创建一个将String路径作为参数的方法。在方法中:
  2. 根据起始目录创建一个新的File对象
  3. 使用listFiles方法获取当前目录中的文件数组
  4. 循环遍历文件数组
    1. 如果是文件,请继续循环
    2. 如果是目录,请打印出名称,然后递归到该新目录路径

您好,感谢您的回复。但我不必遍历目录中的所有项目。我必须直接从目录中列出子目录。B'coz我有很多文件,并且目录中只有几个子目录,因此检查isDirectory()很耗时。请以其他方式回复我。
Lokesh Paunikar,2011年

0

这是我的代码的解决方案。我只是从第一答案开始做了一点小改变。这将仅逐行列出所需目录中的所有文件夹:

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!");
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.