folder_declutter/
process_dir.rsuse std::fs;
use std::path::Path;
use std::time::SystemTime;
pub fn process_dir(dir: &Path, cutoff: SystemTime) {
let mut removed_files = 0;
if let Ok(entries) = fs::read_dir(dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
process_dir(&path, cutoff);
if let Ok(mut entries) = fs::read_dir(&path) {
if entries.next().is_none() {
match fs::remove_dir(&path) {
Ok(_) => println!("\nđď¸ Empty folder deleted: {:?}", path),
Err(e) => eprintln!("Error deleting folder {:?}: {}", path, e),
}
}
}
} else if let Ok(metadata) = fs::metadata(&path) {
if let Ok(modified) = metadata.modified() {
if modified < cutoff {
match fs::remove_file(&path) {
Ok(_) => {
removed_files += 1;
println!("\nđď¸ File deleted: {:?}", path)
}
Err(e) => eprintln!("Error deleting {:?}: {}", path, e),
}
}
}
}
}
}
if removed_files == 0 {
println!("\nâ
Done! No files to delete.");
return;
}
println!("\nâ
Done! {} files removed.", removed_files);
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::{self, File};
use std::io::Write;
use std::path::PathBuf;
use std::time::{Duration, SystemTime};
use tempfile::tempdir;
#[test]
fn test_removes_old_files() {
let temp_dir = tempdir().unwrap();
let file_path: PathBuf = temp_dir.path().join("old_file.txt");
let mut file = File::create(&file_path).unwrap();
writeln!(file, "Some test content").unwrap();
let cutoff = SystemTime::now() + Duration::from_secs(3600);
process_dir(temp_dir.path(), cutoff);
assert!(!file_path.exists(), "File should have been deleted");
}
#[test]
fn test_preserves_new_files() {
let temp_dir = tempdir().unwrap();
let file_path: PathBuf = temp_dir.path().join("new_file.txt");
let mut file = File::create(&file_path).unwrap();
writeln!(file, "Fresh content").unwrap();
let cutoff = SystemTime::now() - Duration::from_secs(3600);
process_dir(temp_dir.path(), cutoff);
assert!(file_path.exists(), "File should not have been deleted");
}
#[test]
fn test_recursive_processing() {
let temp_dir = tempdir().unwrap();
let sub_dir = temp_dir.path().join("subdir");
fs::create_dir(&sub_dir).unwrap();
let old_file: PathBuf = sub_dir.join("old_file.txt");
let new_file: PathBuf = sub_dir.join("new_file.txt");
{
let mut file = File::create(&old_file).unwrap();
writeln!(file, "Old content").unwrap();
}
{
let mut file = File::create(&new_file).unwrap();
writeln!(file, "New content").unwrap();
}
let cutoff = SystemTime::now() + Duration::from_secs(3600);
process_dir(temp_dir.path(), cutoff);
assert!(!old_file.exists(), "old_file should have been deleted recursively");
assert!(!new_file.exists(), "new_file should have been deleted recursively");
let sub_dir2 = temp_dir.path().join("subdir2");
fs::create_dir(&sub_dir2).unwrap();
let preserved_file: PathBuf = sub_dir2.join("preserved.txt");
{
let mut file = File::create(&preserved_file).unwrap();
writeln!(file, "I am still new").unwrap();
}
let cutoff_old = SystemTime::now() - Duration::from_secs(3600);
process_dir(temp_dir.path(), cutoff_old);
assert!(preserved_file.exists(), "File should not have been deleted recursively");
}
#[test]
fn test_empty_folder_deletion() {
let temp_dir = tempdir().unwrap();
let empty_subdir = temp_dir.path().join("empty_folder");
fs::create_dir(&empty_subdir).unwrap();
let cutoff = SystemTime::now() + Duration::from_secs(3600);
process_dir(temp_dir.path(), cutoff);
assert!(!empty_subdir.exists(), "Empty folder should have been deleted");
}
}