3

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")'
Mazyod
  • 22,319
  • 10
  • 92
  • 157

2 Answers2

6

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.

janos
  • 120,954
  • 29
  • 226
  • 236
  • 1
    Yes, I was waiting for this. I still don't know why I can't use [pattern matching](http://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html), but this at least gives me a good idea about this new logical expression sort of thing. – Mazyod Nov 21 '13 at 23:38
  • I'm surprised this doesn't have more votes. Very handy! – young_souvlaki Jan 20 '23 at 01:11
3

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.
fedorqui
  • 275,237
  • 103
  • 548
  • 598