e9571_file_lib/
lib.rs

1use std::fs::{self, File, OpenOptions};
2use std::io::{self, Read, Write};
3use std::path::{Path, PathBuf};
4use chksum_md5 as md5;
5use lazy_static::lazy_static;
6use std::sync::Mutex;
7use std::collections::HashMap;
8
9
10
11lazy_static! {
12    pub static ref FILE_LIST: Mutex<Vec<String>> = Mutex::new(Vec::new());
13    pub static ref FILE_INFO_LIST: Mutex<HashMap<String, String>> = Mutex::new(HashMap::new());
14}
15
16
17/// 检查文件或目录是否存在 (assumed Exists)
18fn exists(path: &str) -> bool {
19    fs::metadata(path).is_ok()
20}
21
22
23pub mod e9571_file_lib {
24    use super::*;
25
26    /// 获取文件夹文件列表 (ListFile)
27    /// Returns a map of file paths to their parent directories
28    pub fn list_file(myfolder: &str) -> Result<HashMap<String, String>, io::Error> {
29        let mut out_put = HashMap::new();
30        let entries = fs::read_dir(myfolder)?;
31
32        for entry in entries {
33            let file = entry?;
34            let path = file.path();
35            let path_str = path.to_str().unwrap_or("").to_string();
36            let parent_str = myfolder.to_string();
37            out_put.insert(path_str, parent_str);
38        }
39        Ok(out_put)
40    }
41
42    /// 遍历文件路径并添加到全局列表 (Visit)
43    /// Adds file paths to the global File_info_list
44    pub fn visit(path: &str) {
45        let mut file_info_list = FILE_INFO_LIST.lock().unwrap();
46        file_info_list.insert(path.to_string(), path.to_string());
47    }
48
49    /// 获取文件 MD5 哈希 (File_MD5)
50    /// Returns the uppercase MD5 hash of a file
51    pub fn file_md5(path: &str) -> String {
52        let file = match File::open(path) {
53            Ok(file) => file,
54            Err(e) => {
55                println!("Open: {}", e);
56                return String::new();
57            }
58        };
59
60        match md5::chksum(file) {
61            Ok(digest) => digest.to_hex_uppercase(),
62            Err(e) => {
63                println!("Checksum: {}", e);
64                String::new()
65            }
66        }
67    }
68
69    /// 重命名文件 (File_Rename)
70    /// Renames a file and prints success or error
71    pub fn file_rename(source_file: &str, target_file: &str) {
72        match fs::rename(source_file, target_file) {
73            Ok(_) => println!("file rename OK!"),
74            Err(e) => println!("file rename Error: {}", e),
75        }
76    }
77
78    /// 遍历文件夹获取文件列表 (GetFilelist)
79    /// Returns a list of all file paths (excluding directories)
80    pub fn get_filelist(path: &str) -> Vec<String> {
81        let mut path_tmp = Vec::new();
82        if let Err(e) = walk_dir_files(path, &mut path_tmp) {
83            println!("filepath.Walk() returned: {}", e);
84        }
85        path_tmp
86    }
87
88    fn walk_dir_files(path: &str, paths: &mut Vec<String>) -> io::Result<()> {
89        for entry in fs::read_dir(path)? {
90            let file = entry?;
91            let file_path = file.path();
92            if file.file_type()?.is_dir() {
93                walk_dir_files(file_path.to_str().unwrap_or(""), paths)?;
94            } else {
95                paths.push(file_path.to_str().unwrap_or("").to_string());
96            }
97        }
98        Ok(())
99    }
100
101    /// 获取指定目录及子目录下的文件,匹配后缀 (WalkDir)
102    /// Returns a list of file paths with the specified suffix (case-insensitive)
103    pub fn walk_dir(dir_pth: &str, suffix: &str) -> Result<Vec<String>, io::Error> {
104        let mut files = Vec::new();
105        let suffix_upper = suffix.to_uppercase();
106        walk_dir_recursive(dir_pth, &suffix_upper, &mut files)?;
107        Ok(files)
108    }
109
110    fn walk_dir_recursive(dir_pth: &str, suffix: &str, files: &mut Vec<String>) -> io::Result<()> {
111        for entry in fs::read_dir(dir_pth)? {
112            let file = entry?;
113            let path = file.path();
114            if file.file_type()?.is_dir() {
115                walk_dir_recursive(path.to_str().unwrap_or(""), suffix, files)?;
116            } else if path.file_name()
117                .and_then(|name| name.to_str())
118                .map(|name| name.to_uppercase().ends_with(suffix))
119                .unwrap_or(false) {
120                files.push(path.to_str().unwrap_or("").to_string());
121            }
122        }
123        Ok(())
124    }
125
126    /// 递归获取所有文件,添加到全局 File_list (GetFiles)
127    /// Populates the global FILE_LIST with file paths
128    pub fn get_files(folder: &str) {
129        if let Err(e) = get_files_recursive(folder) {
130            println!("read dir fail: {}", e);
131        }
132    }
133
134    fn get_files_recursive(folder: &str) -> io::Result<()> {
135        let entries = fs::read_dir(folder)?;
136        let mut file_list = FILE_LIST.lock().unwrap();
137        for entry in entries {
138            let file = entry?;
139            let path = file.path();
140            let path_str = path.to_str().unwrap_or("").to_string();
141            if file.file_type()?.is_dir() {
142                get_files_recursive(&path_str)?;
143            } else {
144                file_list.push(path_str);
145            }
146        }
147        Ok(())
148    }
149
150    /// 获取指定文件夹下所有文件,跳过目录 (GetAllFile)
151    /// Returns a list of file paths, excluding directories
152    pub fn get_all_file(pathname: &str, mut s: Vec<String>) -> Result<Vec<String>, io::Error> {
153        let entries = fs::read_dir(pathname)?;
154        for entry in entries {
155            let file = entry?;
156            if !file.file_type()?.is_dir() {
157                let full_name = format!("{}/{}", pathname, file.file_name().to_str().unwrap_or(""));
158                s.push(full_name);
159            }
160        }
161        Ok(s)
162    }
163
164    /// 获取指定文件夹下所有文件夹 (GetDirList)
165    /// Returns a list of directory paths
166    pub fn get_dir_list(dirpath: &str) -> Result<Vec<String>, io::Error> {
167        let mut dir_list = Vec::new();
168        walk_dir_dirs(dirpath, &mut dir_list)?;
169        Ok(dir_list)
170    }
171
172    fn walk_dir_dirs(path: &str, dirs: &mut Vec<String>) -> io::Result<()> {
173        for entry in fs::read_dir(path)? {
174            let file = entry?;
175            if file.file_type()?.is_dir() {
176                let path_str = file.path().to_str().unwrap_or("").to_string();
177                dirs.push(path_str.clone());
178                walk_dir_dirs(&path_str, dirs)?;
179            }
180        }
181        Ok(())
182    }
183
184    /// 拷贝单个文件 (CopyFile)
185    /// Copies a file from src to dst, returns bytes written and error
186    pub fn copy_file(src_name: &str, dst_name: &str) -> io::Result<(i64, io::Error)> {
187        let mut src = match File::open(src_name) {
188            Ok(file) => file,
189            Err(e) => return Ok((0, e)),
190        };
191        let mut dst = match OpenOptions::new()
192            .write(true)
193            .create(true)
194            .truncate(true)
195            .open(dst_name)
196        {
197            Ok(file) => file,
198            Err(e) => return Ok((0, e)),
199        };
200        match io::copy(&mut src, &mut dst) {
201            Ok(written) => Ok((written as i64, io::Error::new(io::ErrorKind::Other, "No error"))),
202            Err(e) => Ok((0, e)),
203        }
204    }
205
206    /// 拷贝单个文件 (CopyFile1)
207    /// Copies a file from src to dst, ensures sync
208    pub fn copy_file1(src: &str, dst: &str) -> io::Result<()> {
209        let mut src_file = File::open(src)?;
210        let mut dst_file = File::create(dst)?;
211        io::copy(&mut src_file, &mut dst_file)?;
212        dst_file.sync_all()?;
213        Ok(())
214    }
215
216    /// 递归拷贝目录 (CopyDir)
217    /// Copies a directory and its contents recursively
218    pub fn copy_dir(src: &str, dst: &str) -> io::Result<()> {
219        let entries = fs::read_dir(src)?;
220        for entry in entries {
221            let file = entry?;
222            let src_path = file.path();
223            let dst_path = Path::new(dst).join(file.file_name());
224            if file.file_type()?.is_dir() {
225                fs::create_dir_all(&dst_path)?;
226                copy_dir(src_path.to_str().unwrap_or(""), dst_path.to_str().unwrap_or(""))?;
227            } else {
228                copy_file1(src_path.to_str().unwrap_or(""), dst_path.to_str().unwrap_or(""))?;
229            }
230        }
231        Ok(())
232    }
233
234    /// 判断文件是否存在 (CheckFileIsExist)
235    /// Returns true if the file exists
236    pub fn check_file_is_exist(filename: &str) -> bool {
237        fs::metadata(filename).is_ok()
238    }
239
240    /// 判断路径是否为文件夹 (IsDir)
241    /// Returns true if the path is a directory
242    pub fn is_dir(name: &str) -> bool {
243        fs::metadata(name)
244            .map(|metadata| metadata.is_dir())
245            .unwrap_or(false)
246    }
247
248    /// 判断路径是否为文件 (IsFile)
249    /// Returns true if the path is a file
250    pub fn is_file(path: &str) -> bool {
251        !is_dir(path)
252    }
253
254    /// 新建文件,自动创建目录 (Create_New_File)
255    /// Creates a directory if it doesn’t exist, returns the path
256    pub fn create_new_file(file_name: &str) -> Result<String, io::Error> {
257        if check_file_is_exist(file_name) {
258            return Ok(file_name.to_string());
259        }
260        fs::create_dir(file_name)?;
261        Ok(file_name.to_string())
262    }
263
264    /// 递归删除指定目录下的所有文件 (DeleteFilesInDir)
265    /// Deletes all files in a directory, excluding directories
266    pub fn delete_files_in_dir(dir: &str) -> io::Result<()> {
267        for entry in fs::read_dir(dir)? {
268            let file = entry?;
269            if !file.file_type()?.is_dir() {
270                let path = file.path();
271                fs::remove_file(&path).map_err(|e| {
272                    io::Error::new(
273                        io::ErrorKind::Other,
274                        format!("删除文件 {} 时出错: {}", path.display(), e),
275                    )
276                })?;
277                println!("已删除文件: {}", path.display());
278            }
279        }
280        Ok(())
281    }
282}