Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using operators in "find"

Tags:

find

bash

macos

I apologise if this had already been covered before. I am learning find on my OSX Mavericks. I am not quite sure I fully understand the operators.

My folder has 4 files:

123.123
123.abc
abc.123
abc.abc

When I try to "OR" -o operator:

find . \( -name "*.123" -o -name "123.*" \) -print

Output is as expected:

./123.123
./123.abc
./abc.123

But when I take away the bracket / parentheses, i.e.:

find . -name "*.123" -o -name "123.*" -print

... only ./123.abc is printed.

Why....??? I really don't understand how the command is being interpreted by the computer here.

My observation is that ./123.abc fits the second argument (123.*), but not the first (*.123). So it seems somehow, the use of -o before the second argument without brackets lead to the first argument behaving as if it had a "NOT" (!) operator.

like image 718
LD99 Avatar asked Dec 08 '25 09:12

LD99


2 Answers

Taking bracket out makes -print action execute for this condition only:

-name "123.*"

Which prints: ./123.abc

like image 166
anubhava Avatar answered Dec 10 '25 00:12

anubhava


This is a question of operator precedence between the "and" and "or" operators.

find . -name "*.123" -o -name "123.*" -print

is in fact

find . -name "*.123" -o -name "123.*" -a -print

As and has higher priority, this is interpreted as:

find . -name "*.123" -o \( -name "123.*" -a -print \)

If you want your expected behaviour without parenthesis, write that:

sh$ find . -name "*.123" -o -name "123.*"
./abc.123
./123.abc
./123.123

Here the "print" action is implied, and not subject to grouping.

If you want the full-verbose equivalent, you could write:

sh$ find . -name "*.123" -a -print -o -name "123.*" -a -print
./abc.123
./123.abc
./123.123

Which is interpreted as:

find . \( -name "*.123" -a -print \) -o \( -name "123.*" -a -print \)
like image 29
Sylvain Leroux Avatar answered Dec 09 '25 23:12

Sylvain Leroux