过滤通过fs :: read_dir()发现的文件或目录 [英] Filtering files or directories discovered with fs::read_dir()

查看:219
本文介绍了过滤通过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, unwraps 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆