I am trying to find all the files which have 'pillar' in the name (case incentive) and do not contain 'cache' (also case insensitive) with

find . -iname '*pillar*' -and -not -iname '*cache*'

but it not working as I find (among others)


What am I doing wrong?


It looks like you want to avoid looking for files in *cache* directories more than finding files with *pillar* and not *cache* in their name. Then, just tell find not to bother descending into *cache* directories:

find . -iname '*cache*' -prune -o -iname '*pillar*' -print

Or with zsh -o extendedglob:

ls -ld -- (#i)(^*cache*/)#*pillar*

(not strictly equivalent as that would report a foo/pillar-cache file)

Or (less efficient as it descends the whole tree like in @apaul's solution):

ls -ld -- (#i)**/*pillar*~*cache*

Details on the zsh specific globs:

  • (#i): turn on case insensitive matching
  • ^: negation glob operator
  • (...): grouping (like @(...) in ksh).
  • <something>#: zero or more of <something> (like * in regexps).
  • ~: and-not operator (matches on the whole path)
  • **/: 0 or more directory levels (short for (*/)#).

Add the (D) glob qualifier if you want to descend into hidden dires and match hidden files like in the find solution.


The find options you've specified apply on the filename, not on the name of sub-directories.

Here, your filename doesn't contain cache but contains pillar, so it matches.

In your case, you may want to use the -path option. Something like:

find . -iname '*pillar*' -and -not -ipath '*cache*'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.