Skip to content

Instantly share code, notes, and snippets.

@devnote-dev
Last active October 5, 2023 01:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devnote-dev/e8388919ad85dd9a1619b462e7c4a608 to your computer and use it in GitHub Desktop.
Save devnote-dev/e8388919ad85dd9a1619b462e7c4a608 to your computer and use it in GitHub Desktop.
Recursive file stat with Rust
// Bigstat
// (c) 2023 Devonte W <https://github.com/devnote-dev>
//
// Dependencies:
// bytesize = "1.3.0"
// fibers = "0.1"
// futures = "0.1"
use bytesize::ByteSize;
use fibers::{Executor, Spawn, ThreadPoolExecutor};
use futures::future::err;
use std::{env, fs, path::Path, process::exit};
fn recurse_dir<P: AsRef<Path>>(p: P) -> (u64, u64) {
let dir = fs::read_dir(p);
if dir.is_err() {
return (0, 0);
}
let mut files: u64 = 0;
let mut size: u64 = 0;
for path in dir.unwrap() {
let entry = path.unwrap();
let meta = entry.metadata().unwrap();
if meta.is_file() {
files += 1;
size += meta.len();
} else if meta.is_dir() {
let (f, s) = recurse_dir(entry.path());
files += f;
size += s;
}
}
(files, size)
}
fn main() {
let args = env::args();
if args.len() == 1 {
eprintln!("err: no directories specified");
exit(1);
}
let mut paths = Vec::new();
for arg in args.skip(1) {
if fs::metadata(&arg).is_ok() {
paths.push(arg);
} else {
println!("warn: path {arg} not found")
}
}
if paths.is_empty() {
exit(1);
}
let executor = ThreadPoolExecutor::new().unwrap();
for path in paths {
let meta = fs::metadata(&path).unwrap();
if meta.is_file() {
println!("{}: {}", &path, ByteSize(meta.len()));
continue;
}
if meta.is_dir() {
executor.handle().spawn(futures::lazy(move || {
let (files, size) = recurse_dir(&path);
println!("{}: {} ({} files)", &path, ByteSize(size), files);
Ok(())
}));
}
}
executor.handle().spawn(futures::lazy(|| err::<(), ()>(())));
executor.run().unwrap();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment