Почему порядок параметров влияет на файлы, найденные `find`?

Я нашел это странное поведение в find . В зависимости от порядка параметров для find он находит разные файлы.

Например, у меня есть дерево каталогов со следующим контентом.

 . ├── configure.ac ├── Makefile.am └── src ├── hello.c └── Makefile.am 

если я забегу

 find -name '*.cpp' -o -name '*.[chS]' -print0 | xargs -0 echo 

Он перечисляет

 ./src/hello.c 

И если я забегу

 find -name '*.[chS]' -o -name '*.cpp' -print0 | xargs -0 echo 

Он ничего не перечисляет. Обратите внимание, что единственное, что я изменил, это порядок имени файла.

Может ли кто-нибудь объяснить, почему вторая команда не перечисляет какие-либо файлы?

Действие -print0 привязывается только к второму «фильтру» (test in find parlance), поэтому он будет печатать только что-то, если второй фильтр соответствует. Это связано с тем, что оператор по умолчанию в выражении find является and , и связывает более жесткие, чем or ( -o ). т.е. ваше второе выражение оценивается как:

 find -name '*.[chS]' -o \( -name '*.cpp' -print0 \) | xargs -0 echo 

Попробуйте сгруппировать фильтры:

 find \( -name '*.[chS]' -o -name '*.cpp' \) -print0 | xargs -0 echo 

Вы могли бы также сделать это, если бы вам это понравилось:

 find -name '*.[chS]' -print0 -o -name '*.cpp' -print0 | xargs -0 echo