我有这个功能:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.into_iter()
.map(|x| x.map(|entry| entry.path()))
.collect()
}
其实是借自here .功能正常;不幸的是,我真的不明白它是如何工作的。
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"])
测试输出显示了目录和文件,正如它应该的那样。我不知道在哪里放置文件/目录的过滤。不明白为什么mapping里面的mapping:不就是一个简单的路径列表吗?这个表达式内部到底发生了什么?
更新:
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
进行文件/目录检查。对不起:)
最佳答案
让我们一步一步地遍历整个链。
fs::read_dir(dir)?
创建目录的读取句柄,立即传播 Err
如果它发生了,如果没有,unwrap
成功(即 ?
运算符)
.into_iter()
将这个读句柄变成Result<DirEntry>
的迭代器
.map(|x|
x.map(|entry| entry.path())
)
这调用了 path()
如果结果是实际的 DirEntry
,则对迭代器的每个元素执行方法.因为迭代器元素是Result<DirEntry>
而不仅仅是 DirEntry
, 第二个 map()
让你干净地处理这个。你留下了你在输出中看到的路径
.collect()
将此迭代器转回由类型提示(此处为向量)定义的结构
过滤部分可以在调用map()
之前或之后实现将条目变成 PathBuf
.如果您需要根据元素本身而不是 PathBuf
进行过滤,在它之前过滤。如果您可以根据 PathBuf
进行过滤, 对其进行过滤。
filter()
的使用combinator 函数很简单——你给它一个闭包,它会把它应用到每个元素。如果闭包的返回是true
, 元素被保留。如果为 false,则删除该元素。
这是一个例子,只返回目录:
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())
}
关于file - 过滤使用 fs::read_dir() 发现的文件或目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58062887/