鸿蒙PC中使用ohos-sdk完成Rust适配,自动签名编译安装第三方库walkdir是 Rust 递归遍历目录的专用库
欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
AtomGit 仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_rust_cargo
本文讲解鸿蒙 PC 端 Rust 开发环境搭建,鸿蒙基于 musl 库、强制二进制签名,无法直接使用通用 Linux 编译产物。需借助鸿蒙专属包管理器 Harmonybrew,提供两套编译方案:方案一安装 llvm-gcc-compat,零配置开箱即用;方案二仅安装 ohos-sdk,需手动配置 Cargo 链接器,二者都依托 ohos-sdk 完成自动签名编译。
完整的过程可以参考一下:
【OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Rust开发完整开发环境搭建指南】
一、walkdir 库介绍
作用
walkdir 是 Rust 递归遍历目录的专用库,比标准库 std::fs::read_dir 更强大、易用。
核心能力
- 递归遍历文件夹下所有文件+子目录(深度遍历)
- 过滤文件/目录、跳过隐藏文件、按后缀筛选(
.txt/.json等) - 获取文件元信息:大小、是否文件/文件夹、路径、修改时间
- 控制遍历深度,避免无限递归
- 自动处理 IO 错误,友好错误处理
适用场景
批量读取目录文件、日志扫描、文件批量处理、项目文件检索、本地文件同步、静态资源遍历。
二、安装
cargo add walkdir
Cargo.toml 自动添加:
[dependencies]
walkdir = "2"

三、完整无报错示例代码 main.rs
包含 4 个常用场景:基础遍历、只找指定后缀文件、限制遍历深度、过滤隐藏文件
use walkdir::{DirEntry, WalkDir};
use std::path::Path;
fn main() {
// 1. 基础递归遍历当前目录所有文件和文件夹
println!("===== 1. 递归遍历当前目录全部内容 =====");
walk_all_dir(".");
// 2. 只查找 .rs 源码文件
println!("\n===== 2. 筛选所有rs源码文件 =====");
find_file_by_suffix(".", ".rs");
// 3. 只遍历2层目录,不深度递归
println!("\n===== 3. 限制遍历深度最多2级 =====");
walk_limit_depth(".", 2);
// 4. 过滤隐藏文件/隐藏文件夹(以.开头)
println!("\n===== 4. 跳过所有隐藏文件 =====");
walk_skip_hidden(".");
}
/// 基础递归遍历目录,打印所有条目
fn walk_all_dir(root: &str) {
// WalkDir::new 创建目录迭代器
for entry in WalkDir::new(root).into_iter().flatten() {
print_entry_info(&entry);
}
}
/// 按后缀筛选文件(只输出普通文件,跳过文件夹)
fn find_file_by_suffix(root: &str, suffix: &str) {
let walker = WalkDir::new(root).into_iter().flatten();
for entry in walker {
// 只匹配普通文件,跳过文件夹
if entry.file_type().is_file() {
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some(suffix.strip_prefix('.').unwrap()) {
println!("匹配文件: {}", path.display());
}
}
}
}
/// 限制最大遍历深度
fn walk_limit_depth(root: &str, max_depth: usize) {
let walker = WalkDir::new(root)
.max_depth(max_depth) // 限制层级
.into_iter()
.flatten();
for entry in walker {
print_entry_info(&entry);
}
}
/// 过滤隐藏文件/隐藏目录(unix .开头文件)
fn walk_skip_hidden(root: &str) {
let walker = WalkDir::new(root)
.into_iter()
.filter_map(|e| e.ok()) // 忽略IO错误
.filter(|e| {
// 文件名不以 . 开头
!e.file_name()
.to_str()
.map(|s| s.starts_with('.'))
.unwrap_or(false)
});
for entry in walker {
print_entry_info(&entry);
}
}
/// 打印一条目录条目的基础信息
fn print_entry_info(entry: &DirEntry) {
let path = entry.path();
let meta = entry.metadata().unwrap();
let kind = if meta.is_dir() { "文件夹" } else { "文件" };
println!(
"[{}] 路径: {} | 大小: {} bytes",
kind,
path.display(),
meta.len()
);
}

一、库简单回顾
walkdir 是 Rust 递归遍历文件夹的第三方库,对比标准库 std::fs::read_dir,它原生支持递归、深度限制、过滤、错误自动处理,是批量处理本地文件的首选工具。
二、头部导入
use walkdir::{DirEntry, WalkDir};
use std::path::Path;
WalkDir:目录遍历核心迭代器,用来开启文件夹扫描DirEntry:遍历过程中每一个文件/文件夹的封装对象,包含路径、文件类型、元数据、深度等信息std::path::Path:标准库路径类型,统一处理跨系统文件路径
三、入口 main 函数
fn main() {
// 1. 基础递归遍历当前目录所有文件和文件夹
println!("===== 1. 递归遍历当前目录全部内容 =====");
walk_all_dir(".");
// 2. 只查找 .rs 源码文件
println!("\n===== 2. 筛选所有rs源码文件 =====");
find_file_by_suffix(".", ".rs");
// 3. 只遍历2层目录,不深度递归
println!("\n===== 3. 限制遍历深度最多2级 =====");
walk_limit_depth(".", 2);
// 4. 过滤隐藏文件/隐藏文件夹(以.开头)
println!("\n===== 4. 跳过所有隐藏文件 =====");
walk_skip_hidden(".");
}
分4个场景演示最常用4种遍历逻辑:
- 完整递归扫描全部文件目录
- 根据文件后缀筛选指定类型文件
- 限制递归层级,不无限下钻子文件夹
- 过滤系统隐藏文件(Linux/Mac 以
.开头的文件,如.git、.env)
四、函数1:walk_all_dir 基础全量递归遍历
fn walk_all_dir(root: &str) {
// WalkDir::new 创建目录迭代器
for entry in WalkDir::new(root).into_iter().flatten() {
print_entry_info(&entry);
}
}
WalkDir::new(root):传入根目录字符串(.代表当前项目目录),生成递归扫描器.into_iter():转为迭代器,逐个产出目录条目.flatten():WalkDir迭代器产出Result<DirEntry, WalkDirError>,flatten 自动丢弃IO错误,只保留正常读取到的文件;等价于filter_map(|res| res.ok())- 循环遍历每一个
DirEntry,调用统一打印函数输出信息
适用场景:全盘扫描项目、读取目录下所有资源文件
五、函数2:find_file_by_suffix 按后缀筛选文件
fn find_file_by_suffix(root: &str, suffix: &str) {
let walker = WalkDir::new(root).into_iter().flatten();
for entry in walker {
// 只匹配普通文件,跳过文件夹
if entry.file_type().is_file() {
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some(suffix.strip_prefix('.').unwrap()) {
println!("匹配文件: {}", path.display());
}
}
}
}
逐行拆解逻辑
entry.file_type().is_file()
判断当前条目是否为普通文件,过滤掉文件夹、软链接,只保留文件path.extension()获取文件后缀 OsStr(例如main.rs后缀是rs).and_then(|s| s.to_str())将后缀转为字符串,处理无后缀文件的空值suffix.strip_prefix('.').unwrap()
传入参数是.rs,去掉开头的.,拿到纯后缀rs用于对比path.display():安全打印路径,自动处理 Windows / Linux 不同路径分隔符
调用示例 find_file_by_suffix(".", ".rs"):遍历当前目录,只打印所有 Rust 源码文件
六、函数3:walk_limit_depth 限制递归深度
fn walk_limit_depth(root: &str, max_depth: usize) {
let walker = WalkDir::new(root)
.max_depth(max_depth) // 限制层级
.into_iter()
.flatten();
for entry in walker {
print_entry_info(&entry);
}
}
核心方法:.max_depth(数字)
- 根目录深度为0,一级子文件夹深度1,二级深度2
- 示例传参
max_depth=2:最多扫描两层,不会读取三级及更深的子文件夹
用途:防止遍历超大嵌套目录、只需要浅层目录数据,提升扫描速度
补充配套API:
.min_depth(n):只遍历大于等于n层的文件,跳过浅层目录.follow_links(true):跟随软链接(默认关闭,避免循环链接死递归)
七、函数4:walk_skip_hidden 过滤隐藏文件
fn walk_skip_hidden(root: &str) {
let walker = WalkDir::new(root)
.into_iter()
.filter_map(|e| e.ok()) // 忽略IO错误
.filter(|e| {
// 文件名不以 . 开头
!e.file_name()
.to_str()
.map(|s| s.starts_with('.'))
.unwrap_or(false)
});
for entry in walker {
print_entry_info(&entry);
}
}
.filter_map(|e| e.ok()):手动处理Result,读取失败的目录直接丢弃e.file_name():获取当前条目文件名(不含完整路径).map(|s| s.starts_with('.')):判断文件名是否以.开头(隐藏文件标记)!取反,只保留非隐藏文件和文件夹
作用:遍历项目时忽略.git、.vscode、.env等隐藏目录文件
八、公共工具函数 print_entry_info 统一打印文件信息
fn print_entry_info(entry: &DirEntry) {
let path = entry.path();
let meta = entry.metadata().unwrap();
let kind = if meta.is_dir() { "文件夹" } else { "文件" };
println!(
"[{}] 路径: {} | 大小: {} bytes",
kind,
path.display(),
meta.len()
);
}
entry.path():获取完整路径对象entry.metadata():读取文件元数据(大小、类型、修改时间、权限等)meta.is_dir():区分文件夹 / 文件meta.len():文件字节大小,文件夹统一返回0path.display():跨平台友好打印路径,不会出现乱码
九、DirEntry 高频内置方法汇总
entry.path() // &Path 完整路径
entry.file_name() // OsStr 纯文件名
entry.depth() // usize 当前目录层级深度
entry.file_type() // 判断 文件/文件夹/软链接
entry.metadata() // 文件元数据(大小、修改时间)
entry.into_path() // 转为 Owned PathBuf
十、整体业务使用场景
- 批量读取日志文件夹下所有
.log文件解析日志 - 项目静态资源批量复制、压缩、重命名
- 文件查重、统计目录总占用空间
- CLI工具扫描指定格式配置文件
- 过滤隐藏目录,只处理业务代码文件
四、代码逐段详解
1. 导入
use walkdir::{DirEntry, WalkDir};
use std::path::Path;
WalkDir:目录遍历生成器,迭代器主体DirEntry:每一条遍历结果,包含路径、文件类型、元数据等信息
2. 基础遍历 WalkDir::new(root)
WalkDir::new(".")
传入根目录,生成递归迭代器;.into_iter().flatten():自动处理 IO 错误,忽略读取失败目录(等价于 filter_map(|e| e.ok()))
3. DirEntry 常用方法
entry.path() // &Path 文件完整路径
entry.file_name() // OsStr 文件名/文件夹名
entry.file_type() // 判断是文件/目录/软链接
entry.metadata() // 获取文件元数据(大小、修改时间等)
entry.depth() // 当前相对根目录的层级深度
4. 关键配置 API
WalkDir::new(path)
.max_depth(n) // 限制最大递归层级
.follow_links(true) // 跟随软链接(默认false,不跟随防止循环)
.min_depth(n) // 最小遍历层级,跳过浅层目录
5. 文件后缀筛选逻辑
path.extension().and_then(|s| s.to_str()) == Some("rs")
获取文件后缀名字符串,匹配目标后缀,仅打印普通文件,跳过文件夹。
6. 跳过隐藏文件
过滤文件名以 . 开头的条目(Linux/Mac 隐藏文件,如 .git、.env)
五、极简高频片段(可单独复制)
批量获取当前目录所有txt文件路径
use walkdir::WalkDir;
fn get_all_txt() -> Vec<String> {
let mut list = Vec::new();
for entry in WalkDir::new(".").flatten() {
if entry.file_type().is_file() && entry.path().extension().unwrap_or_default() == "txt" {
list.push(entry.path().to_str().unwrap().to_string());
}
}
list
}
获取目录下所有文件总大小
use walkdir::WalkDir;
fn calc_dir_size(root: &str) -> u64 {
WalkDir::new(root)
.flatten()
.filter(|e| e.file_type().is_file())
.map(|e| e.metadata().unwrap().len())
.sum()
}
更多推荐


所有评论(0)