What is the correct syntax for:

find . -type f -name \*.\(shtml\|css\)

This works, but is inelegant:

find . -type f -name \*.shtml > f.txt && find . -type f -name \*.css >> f.txt

How to do the same, but in fewer keystrokes?

link|improve this question

feedback

4 Answers

up vote 6 down vote accepted

You can combine different search expressions with the logical operators -or or -and, so your case can be written as

find . -type f \( -name "*.shtml" -or -name "*.css" \)

This also show that you do not need to escape special shell characters when you use quotes.

Edit

Since -or has lower precedence than the implied -and between -type and the first -name put name part into parentheses as suggested by Chris.

link|improve this answer
Thanks; I find this easy to read. – Dave Jarvis Apr 1 '10 at 2:07
That will also print directories named "*.css". – Teddy Apr 1 '10 at 6:30
1  
And here is how to fix @Teddy's issue: find . -type f \( -name "*.shtml" -or -name "*.css" \) (personally, I would escape the asterisks as the OP did (fewer characters less Shift). – Chris Johnsen Apr 1 '10 at 6:39
@Chris and @Teddy: Thanks, I updated it. – honk Apr 1 '10 at 13:16
Hmm, the parentheses in your updated version are a bit misplaced. The individual parentheses need to end up as separate parameters to find, so they need spaces around them (` ".css") ` results in a single string value; it is the same as (e.g.) ` '.css)' ). Second, the parentheses need to go around whole ‘primaries’ (the open parenthesis needs to be before -name`, not between it and its ‘operand’). – Chris Johnsen Apr 1 '10 at 20:07
show 1 more comment
feedback

You need to parenthesize to only include files:

find . -type f \( -name "*.shtml" -o -name "*.css" \) -print

Bonus: this is POSIX-compliant syntax.

link|improve this answer
feedback

Here is one way to do your first version:

find -type f -regex ".*/.*\.\(shtml\|css\)"
link|improve this answer
Thank you for the regex and fewest keystrokes. – Dave Jarvis Apr 1 '10 at 2:07
Like always a answer very to the point. – honk Apr 1 '10 at 2:33
feedback

I often find myself ending up using egrep, or longer pipes, or perl for even more complex filters:

find . -type f | egrep '\.(shtml|css)$'
find . -type f | perl -lne '/\.(.shtml|css)$/ and print'

It may be somewhat less efficient but that isn't usually a concern, and for more complex stuff it's usually easier to construct and modify.

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.