du: Add threshold argument support
Add --threshold parameter and corresponding logic to skip listing
entires that don't adhere to the threshold
@@ -28,6 +28,7 @@ use std::os::windows::io::AsRawHandle;
#[cfg(windows)]
use std::path::Path;
use std::path::PathBuf;
+use std::str::FromStr;
use std::time::{Duration, UNIX_EPOCH};
use uucore::parse_size::{parse_size, ParseSizeError};
use uucore::InvalidEncodingHandling;
@@ -56,6 +57,7 @@ mod options {
pub const BLOCK_SIZE_1M: &str = "m";
pub const SEPARATE_DIRS: &str = "S";
pub const SUMMARIZE: &str = "s";
+ pub const THRESHOLD: &str = "threshold";
pub const SI: &str = "si";
pub const TIME: &str = "time";
pub const TIME_STYLE: &str = "time-style";
@@ -510,6 +512,17 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.long(options::ONE_FILE_SYSTEM)
.help("skip directories on different file systems")
)
+ .arg(
+ Arg::with_name(options::THRESHOLD)
+ .short("t")
+ .long(options::THRESHOLD)
+ .alias("th")
+ .value_name("SIZE")
+ .number_of_values(1)
+ .allow_hyphen_values(true)
+ .help("exclude entries smaller than SIZE if positive, \
+ or entries greater than SIZE if negative")
+ )
// .arg(
// Arg::with_name("")
// .short("x")
@@ -586,6 +599,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let block_size = u64::try_from(read_block_size(matches.value_of(options::BLOCK_SIZE))).unwrap();
+ let threshold = match matches.value_of(options::THRESHOLD) {
+ Some(s) => Threshold::from_str(s)
+ .unwrap_or_else(|e| crash!(1, "{}", format_error_message(e, s, options::THRESHOLD))),
+ None => Threshold(None, false),
+ };
+
let multiplier: u64 = if matches.is_present(options::SI) {
1000
} else {
@@ -654,6 +673,10 @@ Try '{} --help' for more information.",
// See: http://linux.die.net/man/2/stat
stat.blocks * 512
};
+ if threshold.should_exclude(size) {
+ continue;
+ }
+
if matches.is_present(options::TIME) {
let tm = {
let secs = {
@@ -720,6 +743,35 @@ Try '{} --help' for more information.",
0
}
+struct Threshold(Option<u64>, bool);
+
+impl FromStr for Threshold {
+ type Err = ParseSizeError;
+
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+ let offset = if s.starts_with('-') || s.starts_with('+') {
+ 1
+ } else {
+ 0
+ };
+ let sz = parse_size(&s[offset..])?;
+
+ Ok(Threshold(
+ Some(u64::try_from(sz).unwrap()),
+ s.starts_with('-'),
+ ))
+ }
+}
+
+impl Threshold {
+ fn should_exclude(&self, sz: u64) -> bool {
+ match *self {
+ Threshold(Some(th), is_upper) => (is_upper && sz > th) || (!is_upper && sz < th),
+ Threshold(None, _) => false,
+ }
+ }
+}
+
fn format_error_message(error: ParseSizeError, s: &str, option: &str) -> String {
// NOTE:
// GNU's du echos affected flag, -B or --block-size (-t or --threshold), depending user's selection
