use anyhow::Result;
use chrono::Local;
use std::fs;
use std::path::Path;
use walkdir::WalkDir;
pub fn flatten_directory(root: &str, dry_run: bool) -> Result<()> {
for entry in WalkDir::new(root)
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.path().is_file())
{
let path = entry.path();
let target = Path::new(root).join(path.file_name().unwrap());
if path != target {
let mut final_target = target.clone();
if final_target.exists() {
let timestamp = Local::now().format("%Y%m%d%H%M%S");
let base = path.file_stem().unwrap().to_string_lossy();
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
final_target = Path::new(root).join(format!("{base}_{timestamp}.{ext}"));
}
println!("Moving {} → {}", path.display(), final_target.display());
if !dry_run {
fs::rename(path, final_target)?;
}
}
}
Ok(())
}
pub fn remove_empty_dirs(root: &str, dry_run: bool) -> Result<()> {
let mut dirs = Vec::new();
for entry in WalkDir::new(root)
.min_depth(1)
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.path().is_dir())
{
dirs.push(entry.path().to_path_buf());
}
dirs.sort_by(|a, b| b.components().count().cmp(&a.components().count()));
for path in dirs {
if fs::read_dir(&path)?.next().is_none() && path != Path::new(root) {
println!("Deleting empty directory: {}", path.display());
if !dry_run {
fs::remove_dir(&path)?;
}
}
}
Ok(())
}