walkdir

安装

cargo add walkdir

基础遍历

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        let path: &std::path::Path = dir_entry.path();

        // path.extension()获取结尾
        if path.extension().and_then(|s: &std::ffi::OsStr| s.to_str()) == Some("rs") {
            // 打印path信息
            println!("{}", path.display());
        }
    }
}

遍历文件

dir_entry.file_type().is_file()判断是否是文件

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        if dir_entry.file_type().is_file() {
            let path: &std::path::Path = dir_entry.path();
            println!("文件: {}", path.display());
        }
    }
}

遍历目录

dir_entry.file_type().is_dir()判断是否是目录

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历目录
        if dir_entry.file_type().is_dir() {
            let path: &std::path::Path = dir_entry.path();
            println!("文件: {}", path.display());
        }
    }
}

WalkDir方法

控制深度

min_depth最小遍历深度

WalkDir::new(Path)

  • min_depth(0): 起始目录本身,不输出(Path)
  • min_depth(1): 起始目录下的第一层,输出
use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path")
        .min_depth(1)
        .into_iter()
        .filter_entry(|e| e.file_name().to_str() != Some("target"))
    // 过滤target
    {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        let m = dir_entry.metadata().expect("msg");
        let p = dir_entry.path();
        println!("{}, {}", m.len(), p.display());
    }
}

max_depth最大遍历深度

max_depth(1)最多递归1层

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path").max_depth(1) {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        if dir_entry.file_type().is_dir() {
            let path: &std::path::Path = dir_entry.path();
            println!("文件: {}", path.display());
        }
    }
}

软链接相关

follow_links(true): 一个软链接指向目录,WalkDir会把它当作可进入的目录,继续遍历里面内容

  • false:默认不跟随
  • true:会跟进去
WalkDir::new(".").follow_links(true)

文件系统边界

挂载点,默认跳过挂载点遍历目录

  • 是否限制在同一个文件系统里遍历
  • 避免跨挂载点继续深入
WalkDir::new(".").same_file_system(true)

遍历顺序

⚠️不要再sort_by、sort_by_key中使用元数据排序
过滤目录、文件之后,收集为Vec后再用metadata排序

sort_by

自定义排序规则

WalkDir::new(".").sort_by(|a, b| a.file_name().cmp(b.file_name()))

sort_by_key

按文件个 key 排序

WalkDir::new(".").sort_by_key(|e| e.file_name().to_os_string())

sort_by_file_name文件名排序

  • 按文件名排序
  • 最常用的排序方法之一
use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path")
        .sort_by_file_name() // 文件名排序
        .into_iter()
        // 过滤target
        .filter_entry(|e| e.file_name().to_str() != Some("target"))
    {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        let p = dir_entry.path();
        println!("p: {}", p.display());
    }
}

过滤

方法 作用对象 是否影响递归 是否转换类型
filter_entry WalkDir 条目 是 否
filter 普通迭代器元素 否 否
filter_map 普通迭代器元素 否 是

filter_entry

控制WalkDir“要不要继续递归进去”

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path")
        .into_iter() // 转为引用迭代器
        // 过滤target,原理是阻止递归target目录
        .filter_entry(|e| e.file_name().to_str() != Some("target"))
    {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        let is_symlink = dir_entry.path_is_symlink();
        let p = dir_entry.path();
        println!("{}, {}", is_symlink, p.display());
    }
}

filter

控制“这个元素要不要保留”
前面需要加filter_map(Result::ok)

  • 普通迭代器方法
use walkdir::WalkDir;

fn main() {
    for dir_entry in WalkDir::new("/xx/path")
        .min_depth(1)
        .into_iter()
        .filter_entry(|e| e.file_name().to_str() != Some("target"))
        .filter_map(Result::ok)
        .filter(|f| f.file_type().is_file())
    {
        // 遍历文件
        let m = dir_entry.metadata().expect("msg");
        let p = dir_entry.path();
        println!("{}, {}", m.len(), p.display());
    }
}

filter_map

控制“保留哪些,并顺便做转换”

  • 普通迭代器方法
WalkDir::new(".")
    .into_iter()
    //Ok(entry) → 保留 entry
    // Err(_) → 丢掉
    .filter_map(Result::ok)

DirEntry方法

path

获取路径,返回&Path

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历路径(引用)
        let p: &std::path::Path = dir_entry.path();

        println!("p: {}", p.display());
    }
}

into_path

拿走路径所有权,返回PathBuf

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历路径(获取所有权)
        let p: std::path::PathBuf = dir_entry.into_path();

        println!("p: {}", p.display());
    }
}

file_name

获取文件名,返回&OsStr

写法 返回 特点
to_str() Option<&str> 只有合法 UTF-8 才成功
to_string_lossy() Cow<str> 非法 UTF-8 用 � 替换
to_os_string() OsString 不转 UTF-8,保留系统字符串
use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        if dir_entry.file_type().is_file() {
            let name: &std::ffi::OsStr= dir_entry.file_name();
            
            let n1: std::ffi::OsString = name.to_os_string();
            let n2: Option<&str> = name.to_str();
            let n3: std::borrow::Cow<'_, str> = name.to_string_lossy();

            // 非utf-8的字符会panic
            let n4: String = name.to_str().unwrap().to_string();
            // 转utf-8,非utf-8的变为�
            let n5: String = name.to_string_lossy().to_string();
            println!("文件名: {:?}", n1);
            println!("文件名: {:?}", n2);
            println!("文件名: {}", n3);
            println!("文件名: {}", n4);
            println!("文件名: {}", n5);
        }
    }
}

file_type

获取文件类型,返回FileType

  • 判断
    • is_file()
    • is_dir()
    • is_symlink()
use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        if dir_entry.file_type().is_file() {
            let f_type = dir_entry.file_type();
            println!("文件类型: {:?}", f_type);
        }
    }
}
文件类型: FileType { is_file: true, is_dir: false, is_symlink: false, .. }

metadata

获取元数据,返回Result<Metadata, Error>

  • metadata.len(): 文件大小
  • metadata.is_file(): 是否普通文件
  • metadata.is_dir(): 是否目录
  • metadata.permissions(): 文件权限
  • metadata.modified(): 最后修改时间
  • metadata.created(): 创建时间
  • metadata.accessed(): 最后访问时间
use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        let m_result: Result<std::fs::Metadata, walkdir::Error> = dir_entry.metadata();
        match m_result {
            Ok(m) => {
                println!("len: {}", m.len());
                println!("is_file: {}", m.is_file());
                println!("is_dir: {}", m.is_dir());
                println!("permissions: {:?}", m.permissions());
                println!("modified: {:?}", m.modified());
                println!("created: {:?}", m.created());
                println!("accessed: {:?}", m.accessed());
            }
            Err(e) => {
                println!("e: {:?}", e);
            }
        }
    }
}
len: 11494
is_file: true
is_dir: false
permissions: Permissions(FilePermissions { mode: 0o100644 (-rw-r--r--) })
modified: Ok(SystemTime { tv_sec: 1787123859, tv_nsec: 214114087 })
created: Ok(SystemTime { tv_sec: 1787109788, tv_nsec: 222111098 })
accessed: Ok(SystemTime { tv_sec: 1787109788, tv_nsec: 222111098 })

depth

获取当前深度,返回usize

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        
        let d: usize = dir_entry.depth();
        let p = dir_entry.path();
        println!("{}, {}", d, p.display());
    }
}

路径本身是否是符号链接,返回bool

use walkdir::WalkDir;

fn main() {
    for entry in WalkDir::new("/xx/path") {
        // entry是Result<DirEntry, walkdir::Error>
        let dir_entry: walkdir::DirEntry = entry.unwrap();
        // 遍历文件
        
        let is_symlink: bool = dir_entry.path_is_symlink();
        let p = dir_entry.path();
        println!("{}, {}", is_symlink, p.display());
    }
}
posted @ 2026-08-25 15:36  lxd670  阅读(8)  评论(0)    收藏  举报