-o
. Use
\( \)
to group.find . -name '*.avi' -o -name '*.mkv' -exec cp {} /media \;
find . \( -name '*.avi' -o -name '*.mkv' \) -exec cp {} /media \;
Note that the space between \(
and -name
in
this command is significant.
In find
, two predicates with no operator between them is
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 .. \)
.
In other words, the problematic code means "if name matches
*.avi
, do nothing. Otherwise, if it matches
*.mkv
, execute a command.".
In the correct code, we use \( \)
to group to get the
evaluation order we want. The correct code means "if name matches
*.avi
or *.mkv
, then execute a command", which
was what was intended.
If you're aware of this, you can either ignore this error or group to make it explicit. For example, to decompress all gz files except tar.gz, you can use:
find . -name '*.tar.gz' -o \( -name '*.gz' -exec gzip -d {} + \)
ShellCheck is a static analysis tool for shell scripts. This page is part of its documentation.