mirror of
https://git.proxmox.com/git/rustc
synced 2025-08-14 03:03:34 +00:00
104 lines
3.2 KiB
Rust
104 lines
3.2 KiB
Rust
extern crate docopt;
|
|
extern crate serde;
|
|
#[macro_use]
|
|
extern crate serde_derive;
|
|
extern crate walkdir;
|
|
|
|
use std::io::{self, Write};
|
|
|
|
use docopt::Docopt;
|
|
use walkdir::WalkDir;
|
|
|
|
const USAGE: &'static str = "
|
|
Usage:
|
|
walkdir [options] [<dir> ...]
|
|
|
|
Options:
|
|
-h, --help
|
|
-L, --follow-links Follow symlinks.
|
|
--min-depth NUM Minimum depth.
|
|
--max-depth NUM Maximum depth.
|
|
-n, --fd-max NUM Maximum open file descriptors. [default: 32]
|
|
--tree Show output as a tree.
|
|
--sort Sort the output.
|
|
-q, --ignore-errors Ignore errors.
|
|
-d, --depth Show directory's contents before the directory itself.
|
|
-x, --same-file-system Stay on the same file system.
|
|
";
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[allow(dead_code)]
|
|
struct Args {
|
|
arg_dir: Option<Vec<String>>,
|
|
flag_follow_links: bool,
|
|
flag_min_depth: Option<usize>,
|
|
flag_max_depth: Option<usize>,
|
|
flag_fd_max: usize,
|
|
flag_tree: bool,
|
|
flag_ignore_errors: bool,
|
|
flag_sort: bool,
|
|
flag_depth: bool,
|
|
flag_same_file_system: bool,
|
|
}
|
|
|
|
macro_rules! wout { ($($tt:tt)*) => { {writeln!($($tt)*)}.unwrap() } }
|
|
|
|
fn main() {
|
|
let args: Args = Docopt::new(USAGE)
|
|
.and_then(|d| d.deserialize())
|
|
.unwrap_or_else(|e| e.exit());
|
|
let mind = args.flag_min_depth.unwrap_or(0);
|
|
let maxd = args.flag_max_depth.unwrap_or(::std::usize::MAX);
|
|
for dir in args.arg_dir.unwrap_or(vec![".".to_string()]) {
|
|
let mut walkdir = WalkDir::new(dir)
|
|
.max_open(args.flag_fd_max)
|
|
.follow_links(args.flag_follow_links)
|
|
.min_depth(mind)
|
|
.max_depth(maxd)
|
|
.same_file_system(args.flag_same_file_system);
|
|
if args.flag_sort {
|
|
walkdir = walkdir.sort_by(|a,b| a.file_name().cmp(b.file_name()));
|
|
}
|
|
if args.flag_depth {
|
|
walkdir = walkdir.contents_first(true)
|
|
}
|
|
let it = walkdir.into_iter();
|
|
let mut out = io::BufWriter::new(io::stdout());
|
|
let mut eout = io::stderr();
|
|
if args.flag_tree {
|
|
for dent in it {
|
|
match dent {
|
|
Err(err) => {
|
|
out.flush().unwrap();
|
|
wout!(eout, "ERROR: {}", err);
|
|
}
|
|
Ok(dent) => {
|
|
let name = dent.file_name().to_string_lossy();
|
|
wout!(out, "{}{}", indent(dent.depth()), name);
|
|
}
|
|
}
|
|
}
|
|
} else if args.flag_ignore_errors {
|
|
for dent in it.filter_map(|e| e.ok()) {
|
|
wout!(out, "{}", dent.path().display());
|
|
}
|
|
} else {
|
|
for dent in it {
|
|
match dent {
|
|
Err(err) => {
|
|
out.flush().unwrap();
|
|
wout!(eout, "ERROR: {}", err);
|
|
}
|
|
Ok(dent) => {
|
|
wout!(out, "{}", dent.path().display());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn indent(depth: usize) -> String {
|
|
::std::iter::repeat(' ').take(2 * depth).collect()
|
|
}
|