fs::read_dir 返回一个遍历Result<DirEntry> 的迭代器,它公开了一个DirEntry::path 方法。此方法返回一个PathBuf,它拥有包含文件名的缓冲区。
在您的原始示例中,您尝试将这些转换为 &str - 有两个问题:
-
path() 返回一个 PathBuf,您可以从中获取引用(通过 to_str()),但您没有将 PathBuf 存储在任何地方,因此编译失败并出现此错误:
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:7:18
|
7 | .map(|e| e.path().to_str());
| --------^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
-
to_str() 返回 Option<str> - 如果路径包含任何非 UTF8 字符,则返回 None。你最终会得到一个包含Option<&str> 的Vec。
我建议将它们收集到Vec<PathBuf> 中,就像这样简单:
let paths = fs::read_dir("...")
.unwrap()
.filter_map(|e| e.ok())
.map(|e| e.path())
.collect::<Vec<_>>();
如果你真的需要它们作为字符串,你可以使用:
let paths = fs::read_dir("...")
.unwrap()
.filter_map(|e| e.ok())
.map(|e| e.path().to_string_lossy().into_owned())
.collect::<Vec<_>>();
to_string_lossy() 会将路径转换为字符串,用替换字符替换任何非 utf8 字符。它返回一个Cow<&str> - 它实际上可能拥有也可能不拥有该字符串。为了确保返回一个拥有的字符串,我们调用into_owned()。
最后,如果文件夹不存在,要让它返回一个空列表,你可以使用这样的东西:
let paths : Vec<PathBuf> = match fs::read_dir("/tmsp") {
Err(e) if e.kind() == ErrorKind::NotFound => Vec::new(),
Err(e) => panic!("Unexpected Error! {:?}", e),
Ok(entries) => entries.filter_map(|e| e.ok())
.map(|e| e.path())
.collect()
};
如果出现NotFound 以外的任何错误,上述示例会出现恐慌 - 实际上,您可能会更优雅地处理这种情况。