use std::{io, error::Error, fs, path::Path}; use super::Cmd; use clap::{Arg, ArgAction, Command, ValueHint}; #[derive(Debug, Default)] pub struct Rmdir; impl Cmd for Rmdir { fn cli(&self) -> clap::Command { Command::new("rmdir") .about("remove directories") .author("Nathan Fisher") .version(env!("CARGO_PKG_VERSION")) .args([ Arg::new("parents") .help("remove DIRECTORY and it's ancestors") .short('p') .long("parents") .action(ArgAction::SetTrue), Arg::new("dir") .num_args(1..) .value_name("DIRECTORY") .value_hint(ValueHint::DirPath) .required(true), Arg::new("verbose") .help("output a diagnostic for every directory processed") .short('v') .long("verbose") .action(ArgAction::SetTrue), ]) } fn run(&self, matches: Option<&clap::ArgMatches>) -> Result<(), Box> { let Some(matches) = matches else { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "no input"))); }; if let Some(directories) = matches.get_many::("dir") { for dir in directories { if matches.get_flag("parents") { let path = Path::new(dir); rmdir_recursive(path, matches.get_flag("verbose"))?; } else { fs::remove_dir(dir)?; if matches.get_flag("verbose") { println!("rmdir: removing directory, '{dir}'"); } } } } Ok(()) } fn path(&self) -> Option { Some(crate::Path::Bin) } } fn rmdir_recursive(dir: &Path, verbose: bool) -> Result<(), Box> { fs::remove_dir(dir)?; if verbose { println!("rmdir: removing directory, '{}'", dir.display()); } if let Some(parent) = dir.parent() { if let Some(name) = parent.to_str() { if !name.is_empty() { rmdir_recursive(parent, verbose)?; } } } Ok(()) }