Skip to content
Joachim Ansorg edited this page Nov 12, 2021 · 4 revisions

This action ignores everything before the -o. Use \( \) to group.

Problematic code:

find . -name '*.avi' -o -name '*.mkv' -exec cp {} /media \;

Correct code:

find . \( -name '*.avi' -o -name '*.mkv' \) -exec cp {} /media \;

Rationale:

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.

Exceptions

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

Each individual ShellCheck warning has its own wiki page like SC1000. Use GitHub Wiki's "Pages" feature guerraart8 to find a specific , or see Checks.

Clone this wiki locally