diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index babe7bcdb07..3187f4da204 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -37,6 +37,7 @@ use uucore::display::{print_verbatim, Quotable}; use uucore::error::FromIo; use uucore::error::{UError, UResult}; use uucore::format_usage; +use uucore::parse_glob; use uucore::parse_size::{parse_size, ParseSizeError}; use uucore::InvalidEncodingHandling; #[cfg(windows)] @@ -504,7 +505,7 @@ fn build_exclude_patterns(matches: &ArgMatches) -> UResult> { if matches.is_present(options::VERBOSE) { println!("adding {:?} to the exclude list ", &f); } - match Pattern::new(&f) { + match parse_glob::from_str(&f) { Ok(glob) => exclude_patterns.push(glob), Err(err) => return Err(DuError::InvalidGlob(err.to_string()).into()), } @@ -606,12 +607,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } let path = PathBuf::from(&path_string); + // Check existence of path provided in argument if let Ok(stat) = Stat::new(path, &options) { + // Kick off the computation of disk usage from the initial path let mut inodes: HashSet = HashSet::new(); if let Some(inode) = stat.inode { inodes.insert(inode); } let iter = du(stat, &options, 0, &mut inodes, &excludes); + + // Sum up all the returned `Stat`s and display results let (_, len) = iter.size_hint(); let len = len.unwrap(); for (index, stat) in iter.enumerate() { diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index b421d5e84d2..4eea79d4597 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -747,6 +747,40 @@ fn test_du_exclude_mix() { assert!(result.stdout_str().contains("xcwww")); } +#[test] +// Disable on Windows because we are looking for / +// And the tests would be more complex if we have to support \ too +#[cfg(not(target_os = "windows"))] +fn test_du_complex_exclude_patterns() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + at.mkdir_all("azerty/xcwww/azeaze"); + at.mkdir_all("azerty/xcwww/qzerty"); + at.mkdir_all("azerty/xcwww/amazing"); + + // Negation in glob should work with both ^ and ! + let result = ts + .ucmd() + .arg("--exclude=azerty/*/[^q]*") + .arg("azerty") + .succeeds(); + assert!(!result.stdout_str().contains("amazing")); + assert!(result.stdout_str().contains("qzerty")); + assert!(!result.stdout_str().contains("azeaze")); + assert!(result.stdout_str().contains("xcwww")); + + let result = ts + .ucmd() + .arg("--exclude=azerty/*/[!q]*") + .arg("azerty") + .succeeds(); + assert!(!result.stdout_str().contains("amazing")); + assert!(result.stdout_str().contains("qzerty")); + assert!(!result.stdout_str().contains("azeaze")); + assert!(result.stdout_str().contains("xcwww")); +} + #[test] fn test_du_exclude_several_components() { let ts = TestScenario::new(util_name!());