210

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

4 Answers 4

305

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.

3
  • 29
    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> Commented Jun 13, 2019 at 20:38
  • 3
    one may want to consider -iname instead of -name for case insensitivity Commented Oct 9, 2020 at 16:57
  • also -execdir is preferable wrt -exec Commented Jun 23, 2021 at 9:02
76

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

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

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 
1
  • 3
    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 \( ... \). Commented Feb 7, 2020 at 12:29
9

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. Commented Oct 12, 2012 at 14:01
  • You're right. Added some explanations. Commented Oct 12, 2012 at 14:09

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.