Why find and exec with multiple conditions doesn't work without parenthesis? I have two very similar find commands only one of which works. Since it's relevant, I must mention that there are no files with .c or .hpp extensions.

# That one works
find ~/src/ \( -type f -iname '*.cpp' -or -iname '*.h' -or -iname '*.c' -or -iname '*.hpp' \) -exec echo {} \;
# That one doesn't
find ~/src/ -type f -iname '*.cpp' -or -iname '*.h' -or -iname '*.c' -or -iname '*.hpp' -exec echo {} \;
Well, neither work as you expect. Let's look at the one that "doesn't work" and apply the parentheses and logic that are implied.

find ~/src \( -type f -a -iname '*.cpp' \) -or \( -iname '*.h' \) -or \( -iname '*.c' \) -or \( -iname '*.hpp' \) -exec echo {} \;


No action is applied to files that end in cpp, or file system objects that end in h and c. Only file system objects that end in hpp are echoed because -exec negates the default behavior of find to print. You could add -exec echo {} \; or -print at the end of each enclosed parentheses but that's silly.

Let's fix the "one that works"

find ~/src -type f \( -iname '*.cpp' -or -iname '*.h' -or -iname '*.c' -or -iname '*.hpp' \) -exec echo {} \;