过滤使用 fs::read_dir() 发现的文件或目录

Ale*_*lov 4 iteration mapping filtering file rust

我有这个功能:

fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
    fs::read_dir(dir)?
        .into_iter()
        .map(|x| x.map(|entry| entry.path()))
        .collect()
}
Run Code Online (Sandbox Code Playgroud)

其实是从这里借来的。功能正常;不幸的是,我不太明白它是如何工作的。

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"])
Run Code Online (Sandbox Code Playgroud)

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

更新:

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()
}
Run Code Online (Sandbox Code Playgroud)

插入一个简单的过滤器(总是true)。它至少正在编译,但我仍然不知道应该如何使用entry文件/目录检查。对不起 :)

Séb*_*uld 8

让我们一步一步地遍历链条。

fs::read_dir(dir)?
Run Code Online (Sandbox Code Playgroud)

创建目录的读取句柄,Err如果发生,则立即传播情况,如果没有,unwrap则成功(即?操作符)

.into_iter()
Run Code Online (Sandbox Code Playgroud)

将此读取句柄转换为迭代器Result<DirEntry>

.map(|x|
  x.map(|entry| entry.path())
)
Run Code Online (Sandbox Code Playgroud)

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

.collect()
Run Code Online (Sandbox Code Playgroud)

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

过滤部分可以在调用之前或之后实现,以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())
}
Run Code Online (Sandbox Code Playgroud)