Submind YouTube summaries
Thumbnail for The find command: Implicit -and

The find command: Implicit -and

Watch on YouTube

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.