鸿蒙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更强大、易用。

核心能力

  1. 递归遍历文件夹下所有文件+子目录(深度遍历)
  2. 过滤文件/目录、跳过隐藏文件、按后缀筛选(.txt/.json等)
  3. 获取文件元信息:大小、是否文件/文件夹、路径、修改时间
  4. 控制遍历深度,避免无限递归
  5. 自动处理 IO 错误,友好错误处理

适用场景

批量读取目录文件、日志扫描、文件批量处理、项目文件检索、本地文件同步、静态资源遍历。

二、安装

cargoaddwalkdir

Cargo.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;
  1. WalkDir:目录遍历核心迭代器,用来开启文件夹扫描
  2. DirEntry:遍历过程中每一个文件/文件夹的封装对象,包含路径、文件类型、元数据、深度等信息
  3. 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种遍历逻辑:

  1. 完整递归扫描全部文件目录
  2. 根据文件后缀筛选指定类型文件
  3. 限制递归层级,不无限下钻子文件夹
  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);}}
  1. WalkDir::new(root):传入根目录字符串(.代表当前项目目录),生成递归扫描器
  2. .into_iter():转为迭代器,逐个产出目录条目
  3. .flatten()WalkDir迭代器产出Result<DirEntry, WalkDirError>,flatten 自动丢弃IO错误,只保留正常读取到的文件;等价于filter_map(|res| res.ok())
  4. 循环遍历每一个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());}}}}

逐行拆解逻辑

  1. entry.file_type().is_file()
    判断当前条目是否为普通文件,过滤掉文件夹、软链接,只保留文件
  2. path.extension()获取文件后缀 OsStr(例如main.rs后缀是rs
  3. .and_then(|s| s.to_str())将后缀转为字符串,处理无后缀文件的空值
  4. suffix.strip_prefix('.').unwrap()
    传入参数是.rs,去掉开头的.,拿到纯后缀rs用于对比
  5. 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);}}
  1. .filter_map(|e| e.ok()):手动处理Result,读取失败的目录直接丢弃
  2. e.file_name():获取当前条目文件名(不含完整路径)
  3. .map(|s| s.starts_with('.')):判断文件名是否以.开头(隐藏文件标记)
  4. !取反,只保留非隐藏文件和文件夹
    作用:遍历项目时忽略.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());}
  1. entry.path():获取完整路径对象
  2. entry.metadata():读取文件元数据(大小、类型、修改时间、权限等)
  3. meta.is_dir():区分文件夹 / 文件
  4. meta.len():文件字节大小,文件夹统一返回0
  5. path.display():跨平台友好打印路径,不会出现乱码

九、DirEntry 高频内置方法汇总

entry.path()// &Path 完整路径entry.file_name()// OsStr 纯文件名entry.depth()// usize 当前目录层级深度entry.file_type()// 判断 文件/文件夹/软链接entry.metadata()// 文件元数据(大小、修改时间)entry.into_path()// 转为 Owned PathBuf

十、整体业务使用场景

  1. 批量读取日志文件夹下所有.log文件解析日志
  2. 项目静态资源批量复制、压缩、重命名
  3. 文件查重、统计目录总占用空间
  4. CLI工具扫描指定格式配置文件
  5. 过滤隐藏目录,只处理业务代码文件

四、代码逐段详解

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()}