鸿蒙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 错误,友好错误处理
适用场景
批量读取目录文件、日志扫描、文件批量处理、项目文件检索、本地文件同步、静态资源遍历。
二、安装
cargoaddwalkdirCargo.toml 自动添加:
[dependencies] walkdir = "2"三、完整无报错示例代码 main.rs
包含 4 个常用场景:基础遍历、只找指定后缀文件、限制遍历深度、过滤隐藏文件
usewalkdir::{DirEntry,WalkDir};usestd::path::Path;fnmain(){// 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(".");}/// 基础递归遍历目录,打印所有条目fnwalk_all_dir(root:&str){// WalkDir::new 创建目录迭代器forentryinWalkDir::new(root).into_iter().flatten(){print_entry_info(&entry);}}/// 按后缀筛选文件(只输出普通文件,跳过文件夹)fnfind_file_by_suffix(root:&str,suffix:&str){letwalker=WalkDir::new(root).into_iter().flatten();forentryinwalker{// 只匹配普通文件,跳过文件夹ifentry.file_type().is_file(){letpath=entry.path();ifpath.extension().and_then(|s|s.to_str())==Some(suffix.strip_prefix('.').unwrap()){println!("匹配文件: {}",path.display());}}}}/// 限制最大遍历深度fnwalk_limit_depth(root:&str,max_depth:usize){letwalker=WalkDir::new(root).max_depth(max_depth)// 限制层级.into_iter().flatten();forentryinwalker{print_entry_info(&entry);}}/// 过滤隐藏文件/隐藏目录(unix .开头文件)fnwalk_skip_hidden(root:&str){letwalker=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)});forentryinwalker{print_entry_info(&entry);}}/// 打印一条目录条目的基础信息fnprint_entry_info(entry:&DirEntry){letpath=entry.path();letmeta=entry.metadata().unwrap();letkind=ifmeta.is_dir(){"文件夹"}else{"文件"};println!("[{}] 路径: {} | 大小: {} bytes",kind,path.display(),meta.len());}一、库简单回顾
walkdir是 Rust 递归遍历文件夹的第三方库,对比标准库std::fs::read_dir,它原生支持递归、深度限制、过滤、错误自动处理,是批量处理本地文件的首选工具。
二、头部导入
usewalkdir::{DirEntry,WalkDir};usestd::path::Path;WalkDir:目录遍历核心迭代器,用来开启文件夹扫描DirEntry:遍历过程中每一个文件/文件夹的封装对象,包含路径、文件类型、元数据、深度等信息std::path::Path:标准库路径类型,统一处理跨系统文件路径
三、入口 main 函数
fnmain(){// 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 基础全量递归遍历
fnwalk_all_dir(root:&str){// WalkDir::new 创建目录迭代器forentryinWalkDir::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 按后缀筛选文件
fnfind_file_by_suffix(root:&str,suffix:&str){letwalker=WalkDir::new(root).into_iter().flatten();forentryinwalker{// 只匹配普通文件,跳过文件夹ifentry.file_type().is_file(){letpath=entry.path();ifpath.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 限制递归深度
fnwalk_limit_depth(root:&str,max_depth:usize){letwalker=WalkDir::new(root).max_depth(max_depth)// 限制层级.into_iter().flatten();forentryinwalker{print_entry_info(&entry);}}核心方法:.max_depth(数字)
- 根目录深度为0,一级子文件夹深度1,二级深度2
- 示例传参
max_depth=2:最多扫描两层,不会读取三级及更深的子文件夹
用途:防止遍历超大嵌套目录、只需要浅层目录数据,提升扫描速度
补充配套API:
.min_depth(n):只遍历大于等于n层的文件,跳过浅层目录.follow_links(true):跟随软链接(默认关闭,避免循环链接死递归)
七、函数4:walk_skip_hidden 过滤隐藏文件
fnwalk_skip_hidden(root:&str){letwalker=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)});forentryinwalker{print_entry_info(&entry);}}.filter_map(|e| e.ok()):手动处理Result,读取失败的目录直接丢弃e.file_name():获取当前条目文件名(不含完整路径).map(|s| s.starts_with('.')):判断文件名是否以.开头(隐藏文件标记)!取反,只保留非隐藏文件和文件夹
作用:遍历项目时忽略.git、.vscode、.env等隐藏目录文件
八、公共工具函数 print_entry_info 统一打印文件信息
fnprint_entry_info(entry:&DirEntry){letpath=entry.path();letmeta=entry.metadata().unwrap();letkind=ifmeta.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. 导入
usewalkdir::{DirEntry,WalkDir};usestd::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文件路径
usewalkdir::WalkDir;fnget_all_txt()->Vec<String>{letmutlist=Vec::new();forentryinWalkDir::new(".").flatten(){ifentry.file_type().is_file()&&entry.path().extension().unwrap_or_default()=="txt"{list.push(entry.path().to_str().unwrap().to_string());}}list}获取目录下所有文件总大小
usewalkdir::WalkDir;fncalc_dir_size(root:&str)->u64{WalkDir::new(root).flatten().filter(|e|e.file_type().is_file()).map(|e|e.metadata().unwrap().len()).sum()}