Video summary
The `find` command operates on the principle that there is an implied logical AND relationship between every test and action by default. This means that without explicit grouping, the command evaluates conditions sequentially from left to right, treating each subsequent element as a condition that must follow the previous one. Consequently, the order in which you place these elements significantly alters the outcome; for instance, placing a `print` action at the very beginning causes it to execute first because it always returns true, effectively listing every file in the directory regardless of any subsequent filtering criteria like file type or name.
A more subtle and potentially dangerous trap arises when mixing different logical operators, specifically OR and AND, within a complex expression. If you attempt to find files that match either of two conditions—such as having a specific file extension or exceeding a certain size—and then add an explicit `print` action, the implicit AND operator binds the action only to the immediately preceding condition due to operator precedence rules. Since AND has higher priority than OR, the command interprets the logic as if parentheses were placed around the last condition and the action, leaving the other conditions unconnected to the output action. This results in missing files that clearly meet the search criteria because the action was never applied to them.
This issue becomes even more critical when replacing `print` with the `exec` command, which runs external programs like `ls`. Without proper grouping, an explicit `exec` will only apply to the final condition in the chain, causing it to ignore all other valid matches and produce incorrect results where expected files are omitted. To avoid these pitfalls, one must always use parentheses to explicitly group the entire logical expression before attaching any action. By doing so, you ensure that the action applies to the complete set of conditions rather than just the last one, guaranteeing that `find` returns or executes commands for all files that satisfy any part of your specified criteria.
Read the full video transcript
The book says this about the find
command.
Remember, there is, by default, an
implied and relationship between each
test and action.
That means that this command
is interpreted as if you had typed this.
Since all the operators are and
operators, they are evaluated left to
right.
The book then notes that the order makes
a difference.
If you change the order so that print is
first,
it will be processed first.
Since print always returns true, you'll
see everything in the current directory,
no matter what its file type or name is.
Let's prove that in the shell.
Let's change to the pictures directory.
And I'm going to find
all regular files
and
whose name ends in .png.
And I'm going to print the results.
Works great.
But putting print first
gives us everything in the directory.
This implicit and operator has a more
subtle trap in it, which I encountered
while experimenting with the find
command.
Consider this command
where I want to find files whose names
end in .jpg
or
are greater than 200 K bytes long.
And that works fine.
But if I bring this command back and
explicitly add a print action,
all of a sudden, I get PNG files and no
JPEG files at all.
What happened?
When we don't specify any actions
anywhere, find does the right thing.
It treats the entire expression as a
unit
and adds the implicit and operator along
with print
as if we had typed this.
But when I explicitly added the print
action,
the find command added the implicit and
operator.
That changed everything.
Because and has priority over or,
the print action was now tied to the
size test
as if I had put parentheses here,
leaving no action for the JPEG name
test, and that's why I didn't see any
JPEG files listed.
With an explicit print, I have to fully
parenthesize the expression to get what
I want.
Now, you might be thinking, "What's the
big deal here?
If I put in an explicit print, I get bad
results,
so I'll just drop the print and let find
do the right thing."
Yes, that works.
But what happens if your action is not
print but exec?
You're going to get bad results.
The implicit and, along with priority of
operations,
ties the exec to only the size. None of
the JPEG files will get listed.
Here's the proof direct from the shell.
First, let's do the bad command.
We'll find
the names that end in .jpeg
or
have a size that's greater than 200 KB,
and then see the long listing by sending
it to exec ls -l,
the ever-popular placeholder,
and let's accumulate the results.
And we only get the PNG files, none of
the JPEG files.
To fix this, we need to use parentheses.
Let's bring back the command
and use parentheses to say that we want
the results of this entire expression
to go to exec,
and now we have the correct results.
To summarize, when you add an action
such as exec or print in a complex find
expression,
make sure you use parentheses to ensure
that the action applies to the entire
expression.