72 lines
1.9 KiB
Rust
72 lines
1.9 KiB
Rust
use clap::Parser;
|
|
|
|
mod walk;
|
|
mod directory;
|
|
|
|
use walk::walk;
|
|
|
|
use std::fs::File;
|
|
use std::process::ExitCode;
|
|
|
|
#[derive(Parser, Debug, Clone)]
|
|
pub struct Args {
|
|
#[arg(
|
|
short, long, default_value_t = false,
|
|
help = "keep going if an error occurs",
|
|
long_help = "keep going if an error occurs (ex. unreadable subdirectories in a readable directory)"
|
|
)]
|
|
persistant: bool,
|
|
|
|
#[arg(
|
|
short, long,
|
|
help = "minimize output",
|
|
long_help = "like -t, but does not print \"total: \" before the summary or the newline after. It also surpresses all error messages",
|
|
default_value_t = false,
|
|
)]
|
|
minimal: bool,
|
|
|
|
#[arg(
|
|
short, long,
|
|
help = "only display the total size",
|
|
default_value_t = false,
|
|
)]
|
|
total_only: bool,
|
|
|
|
#[arg(value_parser = validate_path, default_value_t = String::from("."), help = "directory to begin search from")]
|
|
path: String,
|
|
}
|
|
|
|
fn validate_path(s: &str) -> Result<String, String> {
|
|
let here = File::open(s).map_err(|e| e.to_string())?;
|
|
let meta = here.metadata().map_err(|e| e.to_string())?;
|
|
if meta.is_dir() {
|
|
return Ok(s.to_owned())
|
|
} else if meta.is_file() {
|
|
return Err("this is a file (hint: use wc to view file sizes)".to_owned());
|
|
} else {
|
|
return Err("this is not a directory".to_owned());
|
|
}
|
|
}
|
|
|
|
fn main() -> ExitCode {
|
|
let args = Args::parse();
|
|
|
|
let dir_structure = match walk(args.clone()) {
|
|
Ok(dir) => dir,
|
|
Err(e) => return e,
|
|
};
|
|
|
|
if args.minimal {
|
|
print!("{}", dir_structure.size);
|
|
} else {
|
|
let size = dir_structure.size; // copy size before print consumes dir_structure
|
|
dir_structure.print();
|
|
// looks like "print the total unless asked to", but "total: " is to prevent
|
|
// the root from getting lost in massive outputs
|
|
if !args.total_only {
|
|
println!("total: {size}");
|
|
}
|
|
}
|
|
|
|
ExitCode::SUCCESS
|
|
} |