过滤通过fs :: read_dir()发现的文件或目录 [英] Filtering files or directories discovered with fs::read_dir()
问题描述
我有这个功能:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.into_iter()
.map(|x| x.map(|entry| entry.path()))
.collect()
}
它实际上是从此处借来的.功能还可以;不幸的是,我不太了解它是如何工作的.
It's actually borrowed from here. The function is OK; unfortunately, I don't really understand how it works.
Ok(["/home/ey/dir-src/9", "/home/ey/dir-src/11", "/home/ey/dir-src/03 A Letter of Explanation.mp3", "/home/ey/dir-src/02 Egyptian Avenue.mp3", "/home/ey/dir-src/alfa", "/home/ey/dir-src/10"])
测试输出将同时显示目录和文件.我不知道在哪里放置文件/目录过滤.我不明白为什么映射里面的映射:它不只是一个简单的路径列表吗?这个表达式内部到底发生了什么?
The test output shows both directories and files, just as it should. I can't figure out where to put filtering for files/directories. I don't understand why the mapping inside mapping: isn't it just a simple list of paths? What is really happening inside this expression?
UPD:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.into_iter()
.map(|x| x.map(|entry| entry.path()))
.filter(|x| {x.as_ref().map(|entry| entry); true})
.collect()
}
已插入一个普通过滤器(始终为true
).它至少正在编译,但是我仍然看不到应该如何使用entry
进行文件/目录检查.抱歉:)
A trivial filter (always true
) inserted. It is compiling at least, but I still can't see how am I supposed to use entry
for file/directory checking. Sorry :)
推荐答案
让我们逐步走遍整个链条.
Let's walk step by step through the chain.
fs::read_dir(dir)?
创建目录的读取句柄,如果发生Err
情况则立即传播,如果没有发生,则unwrap
成功(即?
运算符)
creates a read handle to the directory, immediately propagates the Err
case if it happens, and if it does not, unwrap
s the success (that's the ?
operator)
.into_iter()
将此读取句柄转换为Result<DirEntry>
.map(|x|
x.map(|entry| entry.path())
)
如果结果是实际的DirEntry
,则此方法在迭代器的每个元素上调用path()
方法.因为迭代器元素是Result<DirEntry>
而不是DirEntry
,所以第二个map()
允许您干净地处理此问题.您将获得在输出中看到的路径
This calls the path()
method on every element of the iterator if the result is an actual DirEntry
. Because the iterator element is Result<DirEntry>
and not just DirEntry
, the second map()
allows you to deal with this cleanly. You're left with the paths you see on output
.collect()
将此迭代器变回由类型提示定义的结构(此处为向量)
turns this iterator back into a structure defined by the type hints (here, a vector)
可以在调用map()
之前或之后实现过滤部分,以将条目转换为PathBuf
.如果需要基于元素本身而不是PathBuf
进行过滤,请在其之前进行过滤.如果可以根据PathBuf
进行过滤,请在其后进行过滤.
The filtering part can be implemented before or after the call to map()
to turn the entry into a PathBuf
. If you need to filter based on the element itself and not the PathBuf
, filter before it. If you can filter based on the PathBuf
, filter after it.
filter()
组合器函数的用法很简单-给它一个闭包,它将把它应用于每个元素.如果闭包的返回值为true
,则保留该元素.如果为假,则删除该元素.
The use of the filter()
combinator function is straightforward - you give it a closure, it will apply it to every element. If the return of the closure is true
, the element is kept. If it is false, the element is dropped.
这里是一个示例,仅返回目录:
Here is an example, to only return directories:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
Ok(fs::read_dir(dir)?
.into_iter()
.filter(|r| r.is_ok()) // Get rid of Err variants for Result<DirEntry>
.map(|r| r.unwrap().path()) // This is safe, since we only have the Ok variants
.filter(|r| r.is_dir()) // Filter out non-folders
.collect())
}
这篇关于过滤通过fs :: read_dir()发现的文件或目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!