walkfile/
lib.rs

1use std::{fs, path::PathBuf, vec};
2use anyhow::{Ok, Result};
3
4/// # WalfFileENtry
5/// * root: 根目录
6/// * child_dirs: root下所有的子文件夹名称
7/// * child_files: root下所有的文件
8#[derive(Debug, Clone)]
9pub struct WalkFileEntry{
10    pub root: PathBuf,
11    pub child_dirs: Vec<String>,
12    pub child_files: Vec<String>,
13}
14
15impl WalkFileEntry {
16    /// 将属性以引用的方式构造成元组
17    /// ```rust
18    /// use std::{path::PathBuf, str::FromStr};
19    /// use crate::walk;
20    /// use anyhow::{Ok, Result};
21    /// fn test_ref_tuple(){
22    ///     let res = walk(&PathBuf::from_str("./").unwrap());
23    ///     let res = match res {
24    ///        Err(e) => panic!("{}", e),
25    ///         Ok(res) => res
26    ///     };
27    ///     let (root, child_dirs, child_files) = res[0].as_tuple_ref();
28    ///     println!("{:?}, {:?}, {:?}", root, child_dirs, child_files);
29    /// }
30    /// ```
31    pub fn as_tuple_ref(&self)->(&PathBuf, &Vec::<String>, &Vec::<String>){
32        (&self.root, &self.child_dirs, &self.child_files)
33    }
34
35    /// 将属性以克隆的方式构造成元组
36    /// ```rust
37    /// use std::{path::PathBuf, str::FromStr};
38    /// use crate::walk;
39    /// use anyhow::{Ok, Result};
40    /// fn test_ref_tuple(){
41    ///     let res = walk(&PathBuf::from_str("./").unwrap());
42    ///     let res = match res {
43    ///        Err(e) => panic!("{}", e),
44    ///         Ok(res) => res
45    ///     };
46    ///     let (root, child_dirs, child_files) = res[0].as_tuple();
47    ///     println!("{:?}, {:?}, {:?}", root, child_dirs, child_files);
48    /// }
49    /// ``` 
50    pub fn as_tuple(&self)->(PathBuf, Vec::<String>, Vec::<String>){
51        (self.root.clone(), self.child_dirs.clone(), self.child_files.clone())
52    }
53}
54
55
56/// 为WalkFileEntry 实现disply
57impl std::fmt::Display for WalkFileEntry {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        write!(f, "root: {}, child_dirs: {:?}, child_files:{:?}", self.root.display(), self.child_dirs, self.child_files)
60    }
61}
62
63/// 遍历指定根目录的入口函数
64/// ```rust
65///use std::{path::PathBuf, str::FromStr};
66/// use crate::walk;
67/// use anyhow::{Ok, Result}; 
68/// fn test_walk(){
69/// let res = walk(&PathBuf::from_str("./").unwrap());
70/// let res = match res {
71///     Err(e) => panic!("{}", e),
72///     Ok(res) => res
73/// };
74/// print!("{}", res[1]);
75/// } 
76/// ```
77pub fn walk(path: &PathBuf)->Result<Vec<WalkFileEntry>>{
78    let mut res:Vec<WalkFileEntry> = Vec::new();
79    walk_dir(path, &mut res)?;
80    Ok(res)
81}
82
83/// 递归的获取子文件夹, 子文件
84fn walk_dir(path: &PathBuf, res: &mut Vec<WalkFileEntry>)->Result<()>{
85    let mut walk = WalkFileEntry{
86        root: path.clone(),
87        child_dirs: vec![],
88        child_files: vec![],
89    };
90    for entry in fs::read_dir(path)?{
91        let entry = entry?;
92        if entry.path().is_dir(){
93            if let Some(p) = entry.path().file_name(){
94                if let Some(p_str) = p.to_str(){
95                    walk.child_dirs.push(p_str.to_string());
96                }
97            }
98            walk_dir(&entry.path(), res)?;
99        }else if entry.path().is_file() {
100            if let Some(p) = entry.path().file_name(){
101                if let Some(p_file) = p.to_str(){
102                    walk.child_files.push(p_file.to_string());
103                }
104            }
105        }
106    }
107    res.push(walk);
108    Ok(())
109}
110
111#[cfg(test)]
112mod test{
113    use std::{path::PathBuf, str::FromStr};
114
115    use crate::walk;
116
117    #[test]
118    fn test_walk(){
119        let res = walk(&PathBuf::from_str("./").unwrap());
120        let res = match res {
121            Err(e) => panic!("{}", e),
122            Ok(res) => res
123        };
124        print!("{:#?}", res);
125    }
126
127    #[test]
128    fn test_ref_tuple(){
129        let res = walk(&PathBuf::from_str("./").unwrap());
130        let res = match res {
131            Err(e) => panic!("{}", e),
132            Ok(res) => res
133        };
134        let (root, child_dirs, child_files) = res[0].as_tuple();
135        println!("{:?}, {:?}, {:?}", root, child_dirs, child_files);
136    }
137}