fs.rs

 1use crate::ResultExt;
 2use anyhow::{Result, bail};
 3use async_fs as fs;
 4use futures_lite::StreamExt;
 5use std::path::{Path, PathBuf};
 6
 7/// Removes all files and directories matching the given predicate
 8pub async fn remove_matching<F>(dir: &Path, predicate: F)
 9where
10    F: Fn(&Path) -> bool,
11{
12    if let Some(mut entries) = fs::read_dir(dir).await.log_err() {
13        while let Some(entry) = entries.next().await {
14            if let Some(entry) = entry.log_err() {
15                let entry_path = entry.path();
16                if predicate(entry_path.as_path()) {
17                    if let Ok(metadata) = fs::metadata(&entry_path).await {
18                        if metadata.is_file() {
19                            fs::remove_file(&entry_path).await.log_err();
20                        } else {
21                            fs::remove_dir_all(&entry_path).await.log_err();
22                        }
23                    }
24                }
25            }
26        }
27    }
28}
29
30pub async fn collect_matching<F>(dir: &Path, predicate: F) -> Vec<PathBuf>
31where
32    F: Fn(&Path) -> bool,
33{
34    let mut matching = vec![];
35
36    if let Some(mut entries) = fs::read_dir(dir).await.log_err() {
37        while let Some(entry) = entries.next().await {
38            if let Some(entry) = entry.log_err() {
39                if predicate(entry.path().as_path()) {
40                    matching.push(entry.path());
41                }
42            }
43        }
44    }
45
46    matching
47}
48
49pub async fn find_file_name_in_dir<F>(dir: &Path, predicate: F) -> Option<PathBuf>
50where
51    F: Fn(&str) -> bool,
52{
53    if let Some(mut entries) = fs::read_dir(dir).await.log_err() {
54        while let Some(entry) = entries.next().await {
55            if let Some(entry) = entry.log_err() {
56                let entry_path = entry.path();
57
58                if let Some(file_name) = entry_path
59                    .file_name()
60                    .map(|file_name| file_name.to_string_lossy())
61                {
62                    if predicate(&file_name) {
63                        return Some(entry_path);
64                    }
65                }
66            }
67        }
68    }
69
70    None
71}
72
73pub async fn move_folder_files_to_folder<P: AsRef<Path>>(
74    source_path: P,
75    target_path: P,
76) -> Result<()> {
77    if !target_path.as_ref().is_dir() {
78        bail!("Folder not found or is not a directory");
79    }
80
81    let mut entries = fs::read_dir(source_path.as_ref()).await?;
82    while let Some(entry) = entries.next().await {
83        let entry = entry?;
84        let old_path = entry.path();
85        let new_path = target_path.as_ref().join(entry.file_name());
86
87        fs::rename(&old_path, &new_path).await?;
88    }
89
90    fs::remove_dir(source_path).await?;
91
92    Ok(())
93}