200

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 ?

Patryk
  • 14,096

4 Answers4

294

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.

rahmu
  • 20,023
Serge
  • 8,541
75

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

 find ./ ! -regex  '.*\(deb\|vmdk\)$'
Alex Leach
  • 7,910
  • 11
    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
49

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
makrom
  • 103
  • 2
    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 07 '20 at 12:29
  • Absolutely incredible. This 'find' command is changing my life. – wheeleruniverse Nov 19 '20 at 06:31
8

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.