Skip to content

fix(find): -mindepth N -maxdepth M with N>M now matches nothing - #821

Open
MsfPablo wants to merge 1 commit into
uutils:mainfrom
MsfPablo:fix-mindepth-greater-than-maxdepth
Open

fix(find): -mindepth N -maxdepth M with N>M now matches nothing#821
MsfPablo wants to merge 1 commit into
uutils:mainfrom
MsfPablo:fix-mindepth-greater-than-maxdepth

Conversation

@MsfPablo

@MsfPablo MsfPablo commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #778.

Problem

find <dir> -mindepth N -maxdepth M with N > M printed entries at the smaller depth instead of nothing. Repro (against current main, commit 1f19cdd):

$ mkdir -p depth-repro/1/2/3 && touch depth-repro/1/f1 depth-repro/f0
$ ./target/debug/find depth-repro -mindepth 2 -maxdepth 1
depth-repro/1
depth-repro/f0

GNU/BSD find print nothing here (no depth is simultaneously >= N and <= M):

$ find depth-repro -mindepth 2 -maxdepth 1   # BSD find, macOS
$                                            # (no output, exit 0)

Root cause

process_dir builds the walker with walkdir's min_depth/max_depth setters (src/find/mod.rs). Those setters silently clamp the contradiction — whichever is set last wins (walkdir src/lib.rs):

pub fn min_depth(mut self, depth: usize) -> Self {
    self.opts.min_depth = depth;
    if self.opts.min_depth > self.opts.max_depth {
        self.opts.min_depth = self.opts.max_depth;   // clamps min DOWN
    }
    self
}
pub fn max_depth(mut self, depth: usize) -> Self {
    self.opts.max_depth = depth;
    if self.opts.max_depth < self.opts.min_depth {
        self.opts.max_depth = self.opts.min_depth;   // clamps max UP
    }
    self
}

uutils calls .max_depth() first, then .min_depth(), so with max_depth=1, min_depth=2 the second call clamps min_depth down to 1 → the walk yields exactly the depth-1 entries.

Fix

Add an explicit guard at the top of process_dir that returns early (no output) when config.min_depth > config.max_depth, matching GNU/BSD find. The walkdir builder is left untouched.

// GNU/BSD find semantics: `-mindepth N -maxdepth M` with N > M matches no
// depth (none is simultaneously >= N and <= M), so the walk yields nothing.
// We must short-circuit here because walkdir's `min_depth`/`max_depth`
// setters silently clamp to resolve the contradiction (whichever is set last
// wins), which would instead surface entries at the smaller depth. See #778.
if config.min_depth > config.max_depth {
    return 0;
}

Verification

  • cargo build --bin find — clean
  • cargo test — 228 lib tests + integration suites pass (0 failures), including two new regression tests:
    • find_mindepth_greater_than_maxdepth (-mindepth 2 -maxdepth 1)
    • find_mindepth_greater_than_maxdepth_reversed_order (-maxdepth 1 -mindepth 2, both orderings must yield nothing)
  • cargo fmt --check — clean
  • cargo clippy --lib -- -D warnings — clean
  • Manual repro now matches GNU/BSD: find depth-repro -mindepth 2 -maxdepth 1 → no output, exit 0

The existing find_mindepth / find_maxdepth / find_zero_maxdepth tests continue to pass unchanged.

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.18%. Comparing base (2a3eac9) to head (248f5cc).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #821      +/-   ##
==========================================
+ Coverage   92.15%   92.18%   +0.03%     
==========================================
  Files          35       35              
  Lines        7377     7412      +35     
  Branches      383      384       +1     
==========================================
+ Hits         6798     6833      +35     
  Misses        438      438              
  Partials      141      141              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed-hq

codspeed-hq Bot commented Aug 10, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 20 untouched benchmarks


Comparing MsfPablo:fix-mindepth-greater-than-maxdepth (248f5cc) with main (2a3eac9)

Open in CodSpeed

@github-actions

Copy link
Copy Markdown

Commit bf2d93f has test result changes:

GNU findutils testsuite:

Test results comparison:
  Current:   TOTAL: 495 / PASSED: 417 / FAILED: 77 / SKIPPED: 1
  Reference: TOTAL: 495 / PASSED: 416 / FAILED: 78 / SKIPPED: 1

Changes from main branch:
  TOTAL: +0
  PASSED: +1
  FAILED: -1

Test improvements (1):
  + tests/find/refuse-noop

bfs testsuite:

Test results comparison:
  Current:   TOTAL: 315 / PASSED: 267 / FAILED: 42 / SKIPPED: 6
  Reference: TOTAL: 313 / PASSED: 267 / FAILED: 40 / SKIPPED: 6

Changes from main branch:
  TOTAL: +2
  PASSED: +0
  FAILED: +2

New test failures (2):
  - gnu/files0_from_ok
  - gnu/okdir_path_empty

@sylvestre

Copy link
Copy Markdown
Contributor

please add a test in test_find

GNU/BSD find semantics: when -mindepth is greater than -maxdepth, no depth
satisfies both bounds, so the walk should produce no output. Previously
uutils find relied on walkdir's min_depth/max_depth setters, which silently
clamp the contradiction (whichever is set last wins). Because process_dir set
max_depth before min_depth, '-mindepth 2 -maxdepth 1' was clamped to
min_depth=max_depth=1 and wrongly printed depth-1 entries.

Add an explicit guard in process_dir that returns early (no output) when
config.min_depth > config.max_depth, before constructing the walkdir builder.

Fixes uutils#778
@sylvestre
sylvestre force-pushed the fix-mindepth-greater-than-maxdepth branch from bf2d93f to 248f5cc Compare August 18, 2026 17:22
Comment thread src/find/mod.rs
matcher: &dyn matchers::Matcher,
quit: &mut bool,
) -> i32 {
// GNU/BSD find semantics: `-mindepth N -maxdepth M` with N > M matches no

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please make this comment shorter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(find): when -mindepth greater than -maxdepth it outputs files, even if must not

2 participants