可以使用 common Streamfilter
从Files.walk
使用String::matches
适当的正则表达式中检索过滤的文件名:
final String SOURCE_DIR = "test";
Files.walk(Paths.get(SOURCE_DIR));
.filter(p -> p.getFileName().toString().matches(".*\\.docx?"))
.forEach(System.out::println);
输出
test\level01\level11\test.doc
test\level02\test-level2.doc
test\t1.doc
test\t3.docx
输入目录结构:
│ t1.doc
│ t2.txt
│ t3.docx
│ t4.bin
│
├───level01
│ │ test.do
│ │
│ └───level11
│ test.doc
│
└───level02
test-level2.doc
更新
可以使用递归解决方案,newDirectoryStream
但需要将其转换为 Stream:
static Stream<Path> readFilesByMaskRecursively(Path start, String mask) {
List<Stream<Path>> sub = new ArrayList<>();
try {
sub.add(StreamSupport.stream( // read files by mask in current dir
Files.newDirectoryStream(start, mask).spliterator(), false));
Files.newDirectoryStream(start, (path) -> path.toFile().isDirectory())
.forEach(path -> sub.add(recursive(path, mask)));
} catch (IOException ioex) {
ioex.printStackTrace();
}
return sub.stream().flatMap(s -> s); // convert to Stream<Path>
}
// test
readFilesByMaskRecursively(Paths.get(SOURCE_DIR), "*.doc*")
.forEach(System.out::println);
输出:
test\t1.doc
test\t3.docx
test\level01\level11\test.doc
test\level02\test-level2.doc
更新 2
可以将前缀**/
添加到PathMatcher
跨目录边界,然后Files.walk
基于 - 的解决方案可以使用简化过滤器,而无需删除特定条目:
String mask = "*.doc*";
PathMatcher maskMatcher = FileSystems.getDefault().getPathMatcher("glob:**/" + mask);
Files.walk(Paths.get(SOURCE_DIR))
.filter(path -> maskMatcher.matches(path))
.forEach(System.out::println);
输出(与递归解决方案相同):
test\level01\level11\test.doc
test\level02\test-level2.doc
test\t1.doc
test\t3.docx