Why doesn't find let me match multiple patterns? Why doesn't find let me match multiple patterns? unix unix

Why doesn't find let me match multiple patterns?


You need to use parentheses in your find command to group your conditions, otherwise only 2nd -name option is effective for -exec command.

find . \( -name '*.html' -or -name '*.xml' \) -exec echo {} \;


find utility

-print == default

If you just want to print file path and names, you have to drop exec echo, because -print is default.:

find . -name '*.html' -or -name '*.xml'

Order dependency

Otherwise, find is read from left to right, argument order is important!

So if you want to specify something, respect and and or precedence:

find . -name '*.html' -exec echo ">"{} \;  -o -name '*.xml' -exec echo "+"{} \;

or

find . -maxdepth 4 \( -name '*.html' -o -name '*.xml' \) -exec echo {} \;

Expression -print0 and xargs command.

But, for most cases, you could consider -print0 with xargs command, like:

find . \( -name '*.html' -o -name '*.xml' \) -print0 |    xargs -0 printf -- "-- %s -\n"

The advantage of doing this is:

  • Only one (or few) fork for thousand of entry found. (Using -exec echo {} \; implies that one subprocess is run for each entry found, while xargs will build a long line with as many argument one command line could hold...)

  • In order to work with filenames containing special character or whitespace, -print0 and xargs -0 will use the NULL character as the filename delimiter.

find ... -exec ... {} ... +

From some years ago, find command accept a new syntax for -exec switch.

Instead of \;, -exec switch could end with a plus sign +.

find . \( -name '*.html' -o -name '*.xml' \) -exec printf -- "-- %s -\n" {} +

With this syntax, find will work like xargs command, building long command lines for reducing forks.