Mazyod
Mazyod

Reputation: 22559

BASH: How to use patterns properly with find

I am desperately trying to write a pattern for find command, but it never works. I want to search for all *.txt and *.h files:

find . -name "*(*.h|*.txt)"

find . -name "(*.h|*.txt)"

find . -name *(*.h|*.txt)

find . -name "*\(*.h|*.txt\)"

find . -name '*("*.h"|"*.txt")'

Upvotes: 3

Views: 2593

Answers (2)

janos
janos

Reputation: 124656

Here you go:

find . -name '*.h' -o -name '*.txt'

If you have more conditions than just the name, for example modification time less then 5 days, then you most probably want to group the multiple name conditions, like this:

find . -mtime -5 \( -name '*.h' -o -name '*.txt' \)

This way your condition becomes "TIME AND (NAME1 OR NAME2)", without the grouping it would be "TIME AND NAME1 OR NAME2" which is not the same, since the latter would be evaluated really as "(TIME AND NAME1) OR NAME2".

Well, it depends on what you want to do, just remember that when you use OR conditions like this, you might need grouping with \( ... \) as in the example above.

UPDATE

If your version of find supports the -regex flag, then another solution:

find . -regex '.*\.\(txt\|h\)'

I think this is more like what you were looking for ;-)

Although patterns in -name pattern can match regular shell patterns like *, ?, and [], it seems they cannot match the extended patterns, even if extglob is enabled.

Upvotes: 6

fedorqui
fedorqui

Reputation: 289825

Use this expression:

find . -type f \( -name "*.h" -or -name "*.txt" \)
  • -type f just finds files.
  • -name \( logical condition \) just matches the file extensions you indicate.

Upvotes: 3

Related Questions