Skip to content

Files and finding

16 min

find, and predicate order

The expression is evaluated left to right, and that is the behaviour.

find walks a tree and tests each path against an expression. The expression is evaluated left to right, and each test has to pass before the next is tried.

The pattern is quoted so the shell does not expand it first: find needs the pattern itself, not the names it happens to match in the current directory.

Try this

Order matters most when an action is involved. find . -name '*.log' -delete deletes the log files. find . -delete -name '*.log' deletes everything, because -delete comes first and always succeeds — the name test is never reached.

-exec runs a command for each match, with {} standing for the path. Terminated with ; it runs once per file; terminated with + it runs once with all of them, which is both faster and safer.

Try this

The real trap is -o. It binds looser than the implicit -a between two tests, so an action written after an alternation belongs only to the branch beside it: find . -name '*.tmp' -o -name '*.log' -delete deletes the logs and leaves every .tmp file exactly where it was.

Both operators short-circuit as well, so for a path that already matched the left side the right side is never evaluated at all. Parentheses — escaped, because the shell wants them too — are how you say what you meant.

Try this

A cleanup script with an ungrouped -o removes half of what you asked for and reports success. That is the shape worth recognising on sight.

The same care applies to piping into xargs: find … | xargs splits its input on whitespace, so a filename with a space in it arrives as two arguments and the command runs against two files that do not exist.

find … -print0 | xargs -0 separates on a NUL byte instead — the one character a filename cannot contain. The two halves have to be used together; -print0 alone changes nothing about how xargs reads.

Try this

$

Files

The files in the sandbox, with their modes, link counts and sizes
ModeLinksSizeName
drwxr-xr-x3exports/
-rw-r--r--135a.txt
drwxr-xr-x3inbox/
-rw-r--r--133b.txt
-rw-r--r--136c.log
drwxr-xr-x2deep/
-rw-r--r--129d.txt
-rwxr-xr-x118script.sh
-rw-r--r--136top.txt