The solution is to bind the two name tests together with parens.
To illustrate this, let's consider a directory with three regular files:
$ ls -a
. .. .hidden1 .hidden2 not_hidden
Now, let's the original command:
$ find . -name ".*" -o -name "*" -exec echo Found {} \;
Found ./not_hidden
Only the non-hidden file is found.
Next, let's add parens to group the two name tests together:
$ find . \( -name ".*" -o -name "*" \) -exec echo Found {} \;
Found .
Found ./not_hidden
Found ./.hidden1
Found ./.hidden2
All files are found.
The solution is to use parens.
More details
In the original command, there is not operator between -name "*" and -exec ... \;. Consequently, find assumes the default operator which is logical-and. Because logical-and binds tighter than logical-or (-o), this means that the command is interpreted as:
find . \( -name ".*" \) -o \( -name "*" -exec echo Found {} \; \)
This means that the exec is run only if the first name condition failed to match.
For more information, see the OPERATORS section in man find.
What happens without -exec
Let's try using a simple -print:
$ find . -name ".*" -o -name "*" -print
./not_hidden
As you can see, -print bound to the -name "*" with the implicit logical-and as above.
But, consider what happens without any action specified:
$ find . -name ".*" -o -name "*"
.
./not_hidden
./.hidden1
./.hidden2
Here, all files were found. The reason is that, in this version, -o is the only operator.
find,chmodwith-R, --recursivecould also be used right, likechmod -R go+w <dir>? – ss_iwe May 25 '17 at 06:24findis to understand that it doesn't find files, it evaluates expressions. It also doesn't really have distinct concepts of "tests" and "actions", they are all operations on the same level. – ilkkachu May 25 '17 at 07:02findlocates and reports dot-files by default... – Kevin Jun 22 '17 at 20:49