147

I would like to search for files that would not match 2 -name conditions. I can do it like so :

find /media/d/ -type f -size +50M ! -name "*deb" ! -name "*vmdk"

and this will yield proper result but can I join these 2 condition with OR somehow ?

0
218

yes, you can:

find /media/d/ -type f -size +50M ! \( -name "*deb" -o -name "*vmdk" \)

Explanation from the POSIX spec:

! expression : Negation of a primary; the unary NOT operator.

( expression ): True if expression is true.

expression -o expression: Alternation of primaries; the OR operator. The second expression shall not be evaluated if the first expression is true.

Note that parenthesis, both opening and closing, are prefixed by a backslash (\) to prevent evaluation by the shell.

4
  • 17
    If you're doing -exec or any other action on the find results, remember to parenthese \( \) the whole criteria, otherwise -exec will apply only to the last -or-ed criterion. To work on all of them, parenthese them: find \( <criterion> -o <criterion> \) -exec <command> Jun 13 '19 at 20:38
  • 1
    this should be the accepted answer
    – swe
    Sep 29 '20 at 13:17
  • 3
    one may want to consider -iname instead of -name for case insensitivity Oct 9 '20 at 16:57
  • also -execdir is preferable wrt -exec Jun 23 at 9:02
65

You can do this using a negated -regex, too:-

 find ./ ! -regex  '.*\(deb\|vmdk\)$'
2
  • 8
    Note that -regex is less portable than -name.
    – jw013
    Oct 12 '12 at 13:54
  • 2
    Should not be the accepted answer. Question asks for a solution using multiple name patterns with find -name. Serge's answer answers that.
    – Veverke
    Nov 24 '20 at 12:04
38

You were close to a solution:

find /media/d/ -type f -size +50M -and ! -name "*deb" -and ! -name "*vmdk"

You can combine the following logic operators in any sequence:

-a   -and      - operator AND
-o   -or       - operator OR
!              - operator NOT
2
  • 1
    It doesn't look like you've actually changed the effect of the user's find command. Note that -a is the default operator if an explicit operator is missing. Also note that if you use -o, there must be a logical grouping of the two name tests. You do this with \( ... \).
    – Kusalananda
    Feb 7 '20 at 12:29
  • Absolutely incredible. This 'find' command is changing my life.
    – jDub9
    Nov 19 '20 at 6:31
7

You can use regular expressions as in:

find /media/d -type f -size +50M ! -regex '\(.*deb\|.*vmdk\)'

Backslash is the escape character; . matches a single character, and * serves to match the previous character zero or more times, so .* means match zero or more characters.

2
  • 1
    Adding an explanation would make your answer better.
    – N.N.
    Oct 12 '12 at 14:01
  • You're right. Added some explanations.
    – user22304
    Oct 12 '12 at 14:09

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.