2

I found this weird behavior in find. Depending on the order of the parameters to find it finds different files.

For example, I have a directory tree with the following content.

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

if I run

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

It lists

./src/hello.c

And if I run

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

It doesn't list anything. Notice that the only thing I changed is the order of the file name.

Can anyone explain why the second command doesn't list any files?

Kotte
  • 2,537

1 Answers1

3

The -print0 action gets bound only to the second -name "filter" (test in find parlance), so it will only print out something if the second filter matches. This is because the default operator in the find expression is and, and binds tighter than or (-o). i.e. your second expression is evaluated as:

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

Try grouping the filters:

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

You could also do this if you felt like it:

find -name '*.[chS]' -print0 -o -name '*.cpp' -print0 | xargs -0 echo
Mat
  • 52,586
  • Huh, that would also explain why giving -print0 as the first parameter lists all the files. Makes sense, but it's also a bit unexpected. Thanks a lot :) – Kotte Apr 22 '14 at 15:33