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.

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
@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 91.97%. Comparing base (1f19cdd) to head (bf2d93f).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #821      +/-   ##
==========================================
+ Coverage   91.93%   91.97%   +0.03%     
==========================================
  Files          35       35              
  Lines        7251     7286      +35     
  Branches      378      379       +1     
==========================================
+ Hits         6666     6701      +35     
  Misses        443      443              
  Partials      142      142              

☔ 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 (bf2d93f) with main (1f19cdd)

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

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

1 participant