Skip to content

find builtin: -path predicate unsupported, -not doesn't consume its argument #950

@chaliy

Description

@chaliy

Summary

Two issues with the find builtin:

  1. -path predicate is not recognized (find: unknown predicate '-path')
  2. -not (and !) skips only itself but does not consume the following predicate+argument, causing the next token to be misinterpreted

Reproduction

# FAIL — -path not supported
mkdir -p /tmp/findtest/.git/objects
touch /tmp/findtest/file.txt
find /tmp/findtest -not -path '*/.git/*'
# expected: /tmp/findtest and /tmp/findtest/file.txt (excluding .git contents)
# actual:   find: unknown predicate '-path'

# FAIL — -not doesn't consume argument
find /tmp/findtest -not -name '*.log'
# If -not only skips itself, -name becomes a bare argument instead of a predicate

Spec tests to add

### find_path_predicate
# find -path should filter by path pattern
mkdir -p /tmp/fp_test/a/b
touch /tmp/fp_test/a/b/file.txt /tmp/fp_test/top.txt
find /tmp/fp_test -path '*/a/*' | sort
### expect
/tmp/fp_test/a/b
/tmp/fp_test/a/b/file.txt
### end

### find_not_name
# find -not -name should negate
mkdir -p /tmp/fn_test
touch /tmp/fn_test/keep.txt /tmp/fn_test/skip.log
find /tmp/fn_test -maxdepth 1 -type f -not -name '*.log' 
### expect
/tmp/fn_test/keep.txt
### end

### find_not_path_exclude
# find -not -path should exclude paths
mkdir -p /tmp/fnp_test/.git /tmp/fnp_test/src
touch /tmp/fnp_test/src/main.rs /tmp/fnp_test/.git/config
find /tmp/fnp_test -type f -not -path '*/.git/*' | sort
### expect
/tmp/fnp_test/src/main.rs
### end

Where to fix

crates/bashkit/src/builtins/ls.rs around lines 471-473:

  1. Add -path predicate: Parse -path PATTERN and filter entries by matching the full path against the glob pattern.

  2. Fix -not/! argument consumption: When encountering -not or !, consume the next predicate AND its arguments (e.g., -not -name '*.log' should consume both -name and '*.log'), then negate the result.

Real-world impact

The wedow/harness list_dir tool falls back to find when tree is unavailable, using find "$path" -not -path '*/.git/*' -not -path '*/node_modules/*'. Both predicates fail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions