Evaluation order of arguments to `find` might be different than expectedSH-2146
In find
, two predicates with no operator between them are considered a logical, short-circuiting AND
(as if using -a
).
E.g., -name '*.mkv' -exec ..
is the same as -name '*.mkv' -a -exec ..
.
-a
has higher precedence than -o
, so -name '*.avi' -o -name '*.mkv' -a -exec ..
is equivalent to -name '*.avi' -o \( -name '*.mkv' -a -exec .. \)
.
The above code essentially implies the following - "if name
matches *.avi
, do nothing. Otherwise, if it matches *.mkv
, execute a command".
It is recommended to use \( \)
to group find
's arguments to ensure they are evaluated in the correct order.
Bad Practice
find . -name '*.avi' -o -name '*.mkv' -exec cp {} /media \;
Recommended:
find . \( -name '*.avi' -o -name '*.mkv' \) -exec cp {} /media \;
Exceptions
If you're already aware of this behavior, you can either ignore this error or group the arguments with parentheses to make the evaluation order explicit.
For example, to decompress all gz
files but not tar.gz
ones, you can use:
find . -name '*.tar.gz' -o \( -name '*.gz' -exec gzip -d {} + \)