Rust 计算机中的目录遍历

Rust 计算机中的目录遍历,rust,Rust,我对Rust还不熟悉,并试图了解基本的目录遍历。我发现的几乎所有示例都使用了walkdir或glob库,我在这方面取得了很好的成功。然而,我现在正试图用stdlib来实现这一点 标准lib文档中有一个函数,列出了以下函数: fn访问(路径:&path,cb:&dyn-fn(&PathBuf))->io::Result{ 对于读取目录中的e(路径){ 设e=e?; 设path=e.path(); if path.is_dir(){ 访问(和路径,cb)?; }如果path.is_file()为,则

我对Rust还不熟悉,并试图了解基本的目录遍历。我发现的几乎所有示例都使用了
walkdir
glob
库,我在这方面取得了很好的成功。然而,我现在正试图用
std
lib来实现这一点

标准lib文档中有一个函数,列出了以下函数:

fn访问(路径:&path,cb:&dyn-fn(&PathBuf))->io::Result{
对于读取目录中的e(路径){
设e=e?;
设path=e.path();
if path.is_dir(){
访问(和路径,cb)?;
}如果path.is_file()为,则为else{
cb&路径;
}
}
好(())
}
我感到困惑的部分是如何在闭包上下文中访问
cb
函数。我很难找到一个例子

例如,我想做一些基本的事情,比如将结果路径收集到
Vec
中。显然,这是行不通的:

fn main(){
//创建新路径
让路径=路径::新建(路径);
让mut files=Vec::new();
访问(路径,| e|{
文件推送(e);
});
}
我收到的错误是:


expected reference`&dyn for您的代码有多个问题,但您收到错误消息的第一个问题是因为
&dyn Fn(&PathBuf)
需要对函数进行引用。您可以通过跟踪错误消息的建议来解决这个错误:<代码>帮助:考虑这里的借用:‘& e文件。推(e)’< /代码>

这就把你的电话变成了:

visit(path, &|e| files.push(e));
但是,此代码仍然不正确,并导致另一个错误:

error[E0596]: cannot borrow `files` as mutable, as it is a captured variable in a `Fn` closure
  --> playground\src\main.rs:48:22
   |
48 |     visit(path, &|e| files.push(e));
   |                      ^^^^^ cannot borrow as mutable
这一次,这是因为你在一个
Fn
(不可变闭包)中变异
文件。要解决此问题,您需要将函数类型更改为
FnMut
(有关更多信息,请参阅):

但你还没做完。现在还有另一个错误,但与第一个错误一样,它对需要更改的内容提出了建议:

error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
  --> playground\src\main.rs:39:13
   |
32 | fn visit(path: &Path, cb: &dyn FnMut(&PathBuf)) -> io::Result<()> {
   |                           -------------------- help: consider changing this to be a mutable reference: `&mut dyn for<'r> std::ops::FnMut(&'r std::path::PathBuf)`
...
39 |             cb(&path);
   |             ^^ `cb` is a `&` reference, so the data it refers to cannot be borrowed as mutable
差不多了,但还有最后一个错误需要解决:

error[E0521]: borrowed data escapes outside of closure
  --> playground\src\main.rs:48:26
   |
47 |     let mut files = Vec::new();
   |         --------- `files` declared here, outside of the closure body
48 |     visit(path, &mut |e| files.push(e));
   |                       -  ^^^^^^^^^^^^^ `e` escapes the closure body here
   |                       |
   |                       `e` is a reference that is only valid in the closure body
您已将闭包定义为引用
PathBuf
&PathBuf
),但您试图将这些引用推入闭包之外的
Vec
,这将不起作用,因为一旦闭包超出范围,这些引用将无效。相反,您应该使用一个拥有的值——只需
PathBuf
。您还需要更新闭包的用法,以传递
PathBuf
,而不是引用:

fn visit(path: &Path, cb: &mut dyn FnMut(PathBuf))
...
cb(path);
终于成功了!下面是完整程序现在的样子。请注意,您还应该
unwrap()
调用
visit()
,因为它返回一个
结果。我还添加了一个简单的
for
循环来打印文件名

use std::path::{Path, PathBuf};
use std::fs::*;
use std::io;

fn visit(path: &Path, cb: &mut dyn FnMut(PathBuf)) -> io::Result<()> {
    for e in read_dir(path)? {
        let e = e?;
        let path = e.path();
        if path.is_dir() {
            visit(&path, cb)?;
        } else if path.is_file() {
            cb(path);
        }
    }
    Ok(())
}

fn main() {
    let path = Path::new("./your/path/here");
    let mut files = Vec::new();
    visit(path, &mut |e| files.push(e)).unwrap();
    for file in files {
        println!("{:?}", file);
    }
}

使用std::path::{path,PathBuf};
使用std::fs::*;
使用std::io;
fn访问(路径:&path,cb:&mut动态FnMut(路径BUF))->io::结果{
对于读取目录中的e(路径){
设e=e?;
设path=e.path();
if path.is_dir(){
访问(和路径,cb)?;
}如果path.is_file()为,则为else{
cb(路径);
}
}
好(())
}
fn main(){
让path=path::new(“/your/path/here”);
让mut files=Vec::new();
访问(路径,&mut|e|files.push(e)).unwrap();
对于文件中的文件{
println!(“{:?}”,文件);
}
}

您的代码有多个问题,但您收到错误消息的第一个问题是因为
&dyn Fn(&PathBuf)
需要对函数的引用。您可以通过跟踪错误消息的建议来解决这个错误:<代码>帮助:考虑这里的借用:‘& e文件。推(e)’< /代码>

这就把你的电话变成了:

visit(path, &|e| files.push(e));
但是,此代码仍然不正确,并导致另一个错误:

error[E0596]: cannot borrow `files` as mutable, as it is a captured variable in a `Fn` closure
  --> playground\src\main.rs:48:22
   |
48 |     visit(path, &|e| files.push(e));
   |                      ^^^^^ cannot borrow as mutable
这一次,这是因为你在一个
Fn
(不可变闭包)中变异
文件。要解决此问题,您需要将函数类型更改为
FnMut
(有关更多信息,请参阅):

但你还没做完。现在还有另一个错误,但与第一个错误一样,它对需要更改的内容提出了建议:

error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
  --> playground\src\main.rs:39:13
   |
32 | fn visit(path: &Path, cb: &dyn FnMut(&PathBuf)) -> io::Result<()> {
   |                           -------------------- help: consider changing this to be a mutable reference: `&mut dyn for<'r> std::ops::FnMut(&'r std::path::PathBuf)`
...
39 |             cb(&path);
   |             ^^ `cb` is a `&` reference, so the data it refers to cannot be borrowed as mutable
差不多了,但还有最后一个错误需要解决:

error[E0521]: borrowed data escapes outside of closure
  --> playground\src\main.rs:48:26
   |
47 |     let mut files = Vec::new();
   |         --------- `files` declared here, outside of the closure body
48 |     visit(path, &mut |e| files.push(e));
   |                       -  ^^^^^^^^^^^^^ `e` escapes the closure body here
   |                       |
   |                       `e` is a reference that is only valid in the closure body
您已将闭包定义为引用
PathBuf
&PathBuf
),但您试图将这些引用推入闭包之外的
Vec
,这将不起作用,因为一旦闭包超出范围,这些引用将无效。相反,您应该使用一个拥有的值——只需
PathBuf
。您还需要更新闭包的用法,以传递
PathBuf
,而不是引用:

fn visit(path: &Path, cb: &mut dyn FnMut(PathBuf))
...
cb(path);
终于成功了!下面是完整程序现在的样子。请注意,您还应该
unwrap()
调用
visit()
,因为它返回一个
结果。我还添加了一个简单的
for
循环来打印文件名

use std::path::{Path, PathBuf};
use std::fs::*;
use std::io;

fn visit(path: &Path, cb: &mut dyn FnMut(PathBuf)) -> io::Result<()> {
    for e in read_dir(path)? {
        let e = e?;
        let path = e.path();
        if path.is_dir() {
            visit(&path, cb)?;
        } else if path.is_file() {
            cb(path);
        }
    }
    Ok(())
}

fn main() {
    let path = Path::new("./your/path/here");
    let mut files = Vec::new();
    visit(path, &mut |e| files.push(e)).unwrap();
    for file in files {
        println!("{:?}", file);
    }
}

使用std::path::{path,PathBuf};
使用std::fs::*;
使用std::io;
fn访问(路径:&path,cb:&mut动态FnMut(路径BUF))->io::结果{
对于读取目录中的e(路径){
设e=e?;
设path=e.path();
if path.is_dir(){
访问(和路径,cb)?;
}如果path.is_file()为,则为else{
cb(路径);
}
}
好(())
}
fn main(){
让path=path::new(“/your/path/here”);
让mut files=Vec::new();
访问(路径,&mut|e|files.push(e)).unwrap();
对于文件中的文件{
println!(“{:?}”,文件);
}
}
<>代码>如果你注意完整的错误消息(你这里不包括),你会看到一个提示你应该做什么来解决这个错误:<代码>帮助:考虑这里的借用:'&e文件.Pube(e)'<代码>。如果您修复了该错误,您将看到需要解决的进一步错误。如果您注意完整的错误消息(此处未包含该消息),您将看到一条提示,提示您应该如何解决该错误