Created SC2146 (markdown)

koalaman
2014-06-22 14:16:14 -07:00
parent a02310b0ed
commit abfe3c02a1

25
SC2146.md Normal file

@@ -0,0 +1,25 @@
## 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.
### Contraindications
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 {} + \)