过滤使用 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()
}

它实际上是从这里借来的。函数正常;不幸的是,我真的不明白它是如何工作的。

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"])

测试输出显示目录和文件,就像它应该的那样。我不知道在哪里过滤文件/目录。我不明白为什么映射内部的映射:它不就是一个简单的路径列表吗?这个表情里面到底发生了什么?

上级:

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

如果结果是实际的DirEntry,这将对迭代器的每个元素调用path()方法。因为迭代器元素是Result<DirEntry>而不仅仅是DirEntry,所以第二个map()允许您干净地处理这个问题。您只剩下在输出中看到的路径

.collect()

将此迭代器转换回由类型提示定义的结构(此处为向量(

过滤部分可以在调用map()之前或之后实现,以将条目转换为PathBuf。如果您需要根据元素本身而不是PathBuf进行过滤,请在它之前过滤。如果可以根据PathBuf进行过滤,则在它之后进行过滤。

filter()组合器函数的使用很简单 - 你给它一个闭包,它会把它应用于每个元素。如果闭包的返回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())
}

您可以合并 2 个过滤器调用并保留 read_dir 的结果。 deref 是能够检查路径是否为 dir,而无需消耗结果

fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
fs::read_dir(dir)?
.map(|r| r.map(|d| d.path()))
.filter(|r| r.is_ok() && r.as_deref().unwrap().is_dir())
.collect()
}

您还可以将过滤器和映射与filter_map结合使用,并使用 ok((.and_then(( 摆脱解包

fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
Ok(fs::read_dir(dir)?
.filter_map(|e| {
e.ok().and_then(|d| {
let p = d.path();
if p.is_dir() {
Some(p)
} else {
None
}
})
})
.collect())
}

最新更新