迭代 std::fs::ReadDir 并仅从路径中获取文件名 [英] Iterate over std::fs::ReadDir and get only filenames from paths
问题描述
我正在尝试弄清楚如何使用 Rust 进行列表理解".我有一个 ReadDir
迭代器,我想映射它并且只获取路径的文件名.我认为它看起来像:
I'm trying to figure out how to do a 'list Comprehension' with rust. I have a ReadDir
iter that I want to map and only get the filenames of the paths. I'm thinking it would look something like:
// get current dir paths
let paths = fs::read_dir(&Path::new(
&env::current_dir().unwrap())).unwrap();
// should contain only filenames
let files_names = paths.map(|&x| {
match (*x).extensions() {
Some(y) => y,
None => //What do I do here? break?
};
我知道我的表达式可能被严重破坏,但是有没有办法使它成为我可以将 file_names
绑定到的单个表达式?
I know my expression is likely horrendously broken, but is there a way to make this a single expression that I can bind file_names
to?
推荐答案
您可能想要使用 Path
的 file_name()
方法来生成文件名如果它是一个普通文件,这就是它返回一个Option
的原因.
You'll probably want to use Path
's file_name()
method which yields the file name if it's a regular file, which is why it returns an Option
.
我想你会想忽略非常规文件的文件名,即对于那些 file_name()
将返回 None
,在这种情况下你可能想要利用 Iterator
的 filter_map
方法,它基本上就像过滤器和地图放在一起,即你能够映射(在这种情况下是路径 ->文件名)并通过将映射结果作为 Option
返回来进行过滤,其中 None
表示您要过滤掉该值.
I imagine you'd want to ignore the file names of things that aren't regular files, i.e. for which file_name()
would return None
, in which case you will probably want to leverage Iterator
's filter_map
method which is basically like filter and map put together, i.e. you're able to map (in this case the path -> file name) and filter by returning the mapped result as an Option
, where None
would signify that you want to filter that value out.
烦人的事情是你必须检查 ReadDir
迭代器返回的每个项目,因为这是一个 Result
类型,所以你必须看看它是否是好的
.如果您只想忽略目录中的非Ok
(即Err
)条目(例如您没有权限的条目),您可以简单地将其转换为一个 Option
使用 Result
的 ok()
方法并将其集成到 filter_map
中.
The annoying thing will be that you have to check each item returned by the ReadDir
iterator, since that's a Result
type, so you'll have to see if it's Ok
. If you just want to ignore non-Ok
(i.e. Err
) entries in the directory (e.g. entries for which you don't have permission), you can simply convert it to an Option
using Result
's ok()
method and integrate that in the filter_map
.
您还必须尝试从返回的 file_name()
创建一个 String
,因为它不一定是 UTF-8.可以使用 map
和 and_then
的组合再次忽略(在本例中)具有非 UTF-8 名称的文件.
You'll also have to attempt to create a String
from the returned file_name()
, since it may not necessarily be UTF-8. Files with non-UTF-8 names can simply be ignored (in this example) again using a combination of map
and and_then
.
如果您让它忽略非Ok
目录条目和不是常规文件的路径(因此在 上返回
) 以及文件名不是 UTF-8 的文件:None
),它会是什么样子file_name()
Here's what it would look like if you make it ignore non-Ok
directory entries and paths which aren't regular files (and thus return None
on file_name()
) as well as files whose file names are not UTF-8:
let paths = fs::read_dir(&Path::new(
&env::current_dir().unwrap())).unwrap();
let names =
paths.filter_map(|entry| {
entry.ok().and_then(|e|
e.path().file_name()
.and_then(|n| n.to_str().map(|s| String::from(s)))
)
}).collect::<Vec<String>>();
如果你不是很熟悉 Rust 的函数式流程控制函数,例如map
、and_then
等在 Result
和 Option
上,然后这是展开后的样子,不忽略错误并且不进行错误处理.我把这留给你:
If you're not very familiar with Rust's functional flow-control functions, e.g. map
, and_then
, etc. on Result
and Option
, then here's what it would look like expanded out, without ignoring errors and without doing error handling. I leave that up to you:
let paths = fs::read_dir(&Path::new(
&env::current_dir().unwrap())).unwrap();
let names =
paths.map(|entry| {
let entry = entry.unwrap();
let entry_path = entry.path();
let file_name = entry_path.file_name().unwrap();
let file_name_as_str = file_name.to_str().unwrap();
let file_name_as_string = String::from(file_name_as_str);
file_name_as_string
}).collect::<Vec<String>>();
这篇关于迭代 std::fs::ReadDir 并仅从路径中获取文件名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!