From 36a919b942b8183b6adc30848c4670743cc93f65 Mon Sep 17 00:00:00 2001 From: Chthonic-Galaxy <162060169+Chthonic-Galaxy@users.noreply.github.com> Date: Sun, 26 Jul 2026 18:50:10 -0300 Subject: [PATCH 1/2] find: visit nothing when -mindepth exceeds -maxdepth No depth can satisfy both bounds when -mindepth is greater than -maxdepth, so nothing should be visited. It forwarded both bounds to walkdir, which clamps min_depth down to max_depth instead of yielding an empty walk, so 'find -mindepth 2 -maxdepth 1' descended and printed every entry at depth 1. Skip the traversal explicitly when the bounds cannot be satisfied, keeping the same end-of-walk handling so '-exec ... +' and '-fprint' behave as they do for a walk that yields no entries. Fixes #778 --- src/find/mod.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/find/mod.rs b/src/find/mod.rs index f6b80751..5b7c7032 100644 --- a/src/find/mod.rs +++ b/src/find/mod.rs @@ -211,6 +211,16 @@ fn process_dir( matcher: &dyn matchers::Matcher, quit: &mut bool, ) -> i32 { + // No depth can satisfy both bounds when -mindepth exceeds -maxdepth, so GNU + // find visits nothing at all. walkdir clamps min_depth down to max_depth + // instead (see `WalkDir::min_depth`), which would make us descend anyway, so + // handle the empty traversal ourselves. + if config.min_depth > config.max_depth { + let mut matcher_io = matchers::MatcherIO::new(deps); + matcher.finished(&mut matcher_io); + return matcher_io.exit_code(); + } + let mut walkdir = WalkDir::new(dir) .contents_first(config.depth_first) .max_depth(config.max_depth) @@ -816,6 +826,67 @@ mod tests { ); } + #[test] + fn find_mindepth_greater_than_maxdepth() { + let deps = FakeDependencies::new(); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-sorted", + "-mindepth", + "2", + "-maxdepth", + "1", + ], + &deps, + ); + + assert_eq!(rc, 0); + assert_eq!(deps.get_output_as_string(), ""); + } + + #[test] + fn find_maxdepth_less_than_mindepth_reversed_order() { + let deps = FakeDependencies::new(); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-sorted", + "-maxdepth", + "1", + "-mindepth", + "2", + ], + &deps, + ); + + assert_eq!(rc, 0); + assert_eq!(deps.get_output_as_string(), ""); + } + + #[test] + fn find_mindepth_greater_than_maxdepth_depth_first() { + let deps = FakeDependencies::new(); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-sorted", + "-mindepth", + "2", + "-maxdepth", + "1", + "-depth", + ], + &deps, + ); + + assert_eq!(rc, 0); + assert_eq!(deps.get_output_as_string(), ""); + } + #[test] fn find_newer() { // create a temp directory and file that are newer than the static From fce24508001874fae4daef8286da0a9bd516de51 Mon Sep 17 00:00:00 2001 From: Chthonic-Galaxy <162060169+Chthonic-Galaxy@users.noreply.github.com> Date: Mon, 27 Jul 2026 19:04:21 -0300 Subject: [PATCH 2/2] find: move the depth-bound tests to tests/test_find.rs --- src/find/mod.rs | 61 ---------------------------------------------- tests/test_find.rs | 34 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 61 deletions(-) diff --git a/src/find/mod.rs b/src/find/mod.rs index 5b7c7032..47f1f8b9 100644 --- a/src/find/mod.rs +++ b/src/find/mod.rs @@ -826,67 +826,6 @@ mod tests { ); } - #[test] - fn find_mindepth_greater_than_maxdepth() { - let deps = FakeDependencies::new(); - let rc = find_main( - &[ - "find", - &fix_up_slashes("./test_data/depth"), - "-sorted", - "-mindepth", - "2", - "-maxdepth", - "1", - ], - &deps, - ); - - assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), ""); - } - - #[test] - fn find_maxdepth_less_than_mindepth_reversed_order() { - let deps = FakeDependencies::new(); - let rc = find_main( - &[ - "find", - &fix_up_slashes("./test_data/depth"), - "-sorted", - "-maxdepth", - "1", - "-mindepth", - "2", - ], - &deps, - ); - - assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), ""); - } - - #[test] - fn find_mindepth_greater_than_maxdepth_depth_first() { - let deps = FakeDependencies::new(); - let rc = find_main( - &[ - "find", - &fix_up_slashes("./test_data/depth"), - "-sorted", - "-mindepth", - "2", - "-maxdepth", - "1", - "-depth", - ], - &deps, - ); - - assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), ""); - } - #[test] fn find_newer() { // create a temp directory and file that are newer than the static diff --git a/tests/test_find.rs b/tests/test_find.rs index 2fbdff37..acf7bda8 100644 --- a/tests/test_find.rs +++ b/tests/test_find.rs @@ -1130,6 +1130,40 @@ fn find_ls_unmapped_owner_renders_numeric_id() { .stdout_contains(unmapped.to_string()); } +#[test] +fn find_mindepth_greater_than_maxdepth() { + ucmd() + .args(&["./test_data/depth", "-mindepth", "2", "-maxdepth", "1"]) + .succeeds() + .no_stderr() + .no_stdout(); +} + +#[test] +fn find_maxdepth_less_than_mindepth_reversed_order() { + ucmd() + .args(&["./test_data/depth", "-maxdepth", "1", "-mindepth", "2"]) + .succeeds() + .no_stderr() + .no_stdout(); +} + +#[test] +fn find_mindepth_greater_than_maxdepth_depth_first() { + ucmd() + .args(&[ + "./test_data/depth", + "-mindepth", + "2", + "-maxdepth", + "1", + "-depth", + ]) + .succeeds() + .no_stderr() + .no_stdout(); +} + #[test] #[cfg(unix)] fn find_slashes() {