find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt"
é a abreviação de:
find . \( \( -type f -a -name "*.htm*" \) -o \
\( -name "*.js*" \) -o \
\( -name "*.txt" \) \
\) -a -print
Isto é, porque nenhum predicado action é especificado (apenas condições ), uma ação -print é implicitamente adicionada para os arquivos que correspondem às condições.
(e, a propósito, que imprime arquivos .js não regulares (o -type f se aplica somente a arquivos .htm )).
Enquanto:
find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \
-exec sh -c 'echo "$0"' {} \;
é a abreviação de:
find . \( -type f -a -name "*.htm*" \) -o \
\( -name "*.js*" \) -o \
\( -name "*.txt" -a -exec sh -c 'echo "$0"' {} \; \)
Para find (como em vários idiomas), AND ( -a ; implícito quando omitido) tem precedência sobre OR ( -o ) e adição um predicado de ação explícito (aqui -exec ) cancela a ação implícita -print vista acima. Aqui você quer:
find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) \
-exec sh -c 'echo "$0"' {} \;
Ou:
find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -exec sh -c '
for i do
echo "$i"
done' sh {} +
Para evitar a execução de um sh por arquivo.