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());
}
}
path_is_symlink
路径本身是否是符号链接,返回
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());
}
}

浙公网安备 33010602011771号