当前位置:   article > 正文

rust递归遍历磁盘目录及文件

rust递归遍历磁盘目录及文件

 Std库实现

  1. //遍历dir目录,找出修改日期距离当前超过age天的文件名称,存入file_list中
  2. fn visit_dir(dir: &Path, file_list: &mut Vec<String>, age: u64) -> io::Result<()> {
  3. if dir.is_dir() {
  4. for entry in fs::read_dir(dir)? {
  5. let entry = entry?;
  6. let path = entry.path();
  7. if path.is_dir() {
  8. visit_dir(&path, file_list, age)?;
  9. } else {
  10. let file_matedata = fs::metadata(entry.path()).unwrap();
  11. let modify_time = file_matedata.modified()?;
  12. if modify_time + Duration::from_secs(age * 24 * 60 * 60) < SystemTime::now(){
  13. file_list.push(entry.path().to_str().unwrap().to_string());
  14. }
  15. }
  16. }
  17. }
  18. Ok(())
  19. }
  20. //遍历dir目录,找出空目录(内部无文件,无目录)
  21. fn get_empty_dir(dir: &Path, dir_list: &mut Vec<String>) -> io::Result<()>{
  22. if !dir.is_dir() {
  23. return Ok(());
  24. }
  25. let read_dir = fs::read_dir(dir)?;
  26. let cnt = read_dir.count();
  27. if cnt == 0 {
  28. dir_list.push(dir.to_str().unwrap().to_owned());
  29. return Ok(());
  30. }
  31. let read_dir = fs::read_dir(dir)?;
  32. for entry in read_dir{
  33. let entry = entry?;
  34. let path = entry.path();
  35. if path.is_dir() {
  36. get_empty_dir(path.as_path(), dir_list)?;
  37. }
  38. }
  39. Ok(())
  40. }

上述函数实现比较直接,需要注意fs::read_dir()函数返回值后面的?宏,从read_dir返回值中提取结果。如visit_dir、get_empty_dir函数定义返回值不是io::Result类型,使用?宏,会报错。因为?宏还涉及错误传播,需要io::Result参与。

Tokio实现

Rust的异步递归函数实现比较繁琐,为了简化,导入如下Crate:

async-recursion = "1.0.5"
  1. use async_recursion::async_recursion;
  2. #[async_recursion]
  3. async fn visit_dir_async(dir: &Path, file_list: &mut Vec<String>, age: u64) {
  4. if dir.is_dir() {
  5. //for entry in tokio::fs::read_dir(dir).flat_map().await? {
  6. let mut entries = tokio::fs::read_dir(dir).await.unwrap();
  7. while let Some(entry) = entries.next_entry().await.unwrap() {
  8. let path = entry.path();
  9. if path.is_dir() {
  10. visit_dir_async(&path, file_list, age).await;
  11. } else {
  12. let file_matedata = tokio::fs::metadata(entry.path()).await.unwrap();
  13. let modify_time = file_matedata.modified().unwrap();
  14. if modify_time + Duration::from_secs(age * 24 * 60 * 60) < SystemTime::now(){
  15. file_list.push(entry.path().to_str().unwrap().to_string());
  16. }
  17. }
  18. }
  19. }
  20. ()
  21. }
  22. #[async_recursion]
  23. async fn get_empty_dir_async(dir: &Path, dir_list: &mut Vec<String>) {
  24. println!("check path:{}", dir.to_str().unwrap());
  25. if !dir.is_dir() {
  26. return;
  27. }
  28. let mut read_dir = tokio::fs::read_dir(dir).await.unwrap();
  29. if let None = read_dir.next_entry().await.unwrap(){
  30. println!("find none path");
  31. dir_list.push(dir.to_str().unwrap().to_owned());
  32. return;
  33. }
  34. let mut read_dir = tokio::fs::read_dir(dir).await.unwrap();
  35. while let Some(entry) = read_dir.next_entry().await.unwrap(){
  36. let path = entry.path();
  37. if path.is_dir() {
  38. get_empty_dir_async(path.as_path(), dir_list).await;
  39. }
  40. }
  41. }

调用

  1. use tokio::io::{self, BufReader, AsyncBufReadExt, BufWriter, AsyncWriteExt};
  2. use tokio::fs::{File, try_exists, remove_file, read_to_string, copy, read_dir};
  3. use std::path::{PathBuf};
  4. use std::fs::File as fsFile;
  5. use std::fs;
  6. use std::path::Path;
  7. use std::fs::{DirEntry};
  8. use std::time::{Duration, SystemTime};
  9. #[tokio::main]
  10. async fn main() -> io::Result<()> {
  11. let source_dir = "E:\\xxxxxx\\Log\\";
  12. //获取目录中的全部文件
  13. let mut file_list: Vec<String> = Vec::new();
  14. let path = Path::new(source_dir);
  15. visit_dir(path, &mut file_list, 30)?;
  16. for file in file_list{
  17. println!("{}", file);
  18. }
  19. let mut empty_file_list: Vec<String> = Vec::new();
  20. let path = Path::new(source_dir);
  21. get_empty_dir(path, &mut empty_file_list)?;
  22. for dir in empty_file_list{
  23. println!("{}", dir);
  24. }
  25. println!("====tokio==================================");
  26. let source_dir = "E:\\xxxxxx\\Log\\";
  27. //获取目录中的全部文件
  28. let mut file_list: Vec<String> = Vec::new();
  29. let path = Path::new(source_dir);
  30. visit_dir_async(path, &mut file_list, 30).await;
  31. for dir in file_list{
  32. println!("tokio {}", dir);
  33. }
  34. println!("====tokio==================================");
  35. let mut empty_file_list: Vec<String> = Vec::new();
  36. get_empty_dir_async(path, &mut empty_file_list).await;
  37. for dir in empty_file_list{
  38. println!("tokio {}", dir);
  39. }
  40. Ok(())
  41. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/121346
推荐阅读
相关标签
  

闽ICP备14008679号