首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >过滤使用fs::read_dir()发现的文件或目录

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

Stack Overflow用户
提问于 2019-09-23 20:52:15
回答 2查看 1.4K关注 0票数 3

我有这个函数:

代码语言:javascript
复制
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
    fs::read_dir(dir)?
        .into_iter()
        .map(|x| x.map(|entry| entry.path()))
        .collect()
}

它实际上是从here借来的。这个函数还可以;不幸的是,我并不真正理解它是如何工作的。

代码语言:javascript
复制
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"])

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

更新:

代码语言:javascript
复制
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进行文件/目录检查。对不起:)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-09-23 21:01:30

让我们一步一步地走完这条链。

代码语言:javascript
复制
fs::read_dir(dir)?

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

代码语言:javascript
复制
.into_iter()

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

代码语言:javascript
复制
.map(|x|
  x.map(|entry| entry.path())
)

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

代码语言:javascript
复制
.collect()

将此迭代器转换回由类型提示定义的结构(这里是一个向量)

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

filter()组合器函数的使用很简单--你给它一个闭包,它会把它应用到每个元素上。如果闭包的返回值为true,则保留该元素。如果为false,则删除该元素。

下面是一个仅返回目录的示例:

代码语言:javascript
复制
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())
}
票数 4
EN

Stack Overflow用户

发布于 2021-06-12 00:25:44

您可以合并2个filter调用并保留来自read_dir的结果。deref将能够检查路径是否为dir,而不使用结果。

代码语言:javascript
复制
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()取消解包。

代码语言:javascript
复制
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())
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58062887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档