2
find . -name "*.[hc]|*.cc"

The above doesn't work,why?

UPDATE

How do I find these 3 kinds of files with a single pattern?

Michael Lowman
  • 3,584
  • 19
  • 36
kernel
  • 8,211
  • 5
  • 18
  • 14

2 Answers2

5

It doesn't work because -name expects a shell pattern. You can use -regex instead, or just assemble your pattern like so:

find . -name '*.c' -o -name '*.h' -o -name '*.cc'

Edit
To do this with a single pattern you'll want a regex:

find . -regextype posix-extended -regex '.*\.(c|h|cc)'

You could do it with the default emacs regexes, I'm sure; I don't use them or know the main differences so I picked the one I know.

If you really want to use a single shellglob, you're out of luck: the only syntax for multiple strings is {a,b}, and this is not supported by find. But there's nothing wrong with the sort of command building/chaining in my first example. It's how find is intended to be used.

mdpc
  • 11,698
  • 28
  • 51
  • 65
Michael Lowman
  • 3,584
  • 19
  • 36
  • P.S. I know you're not using a regex there, but you're mixing syntaxes: the `|` is regex-only, just like the `*` is shell-pattern-only – Michael Lowman Jul 14 '11 at 14:02
  • Is it possible to do with a single shell pattern? – kernel Jul 14 '11 at 14:14
  • And it seems wrong,the conditions are `AND`ed,but I want `OR` – kernel Jul 14 '11 at 14:16
  • @kernel the `-o` means or. This will match any file that ends in `.c` OR `.h` OR `.cc`. are you saying that this command doesn't produce the output you expect? – Michael Lowman Jul 14 '11 at 16:05
  • Is it possible to do with a single **shell** pattern? – kernel Jul 14 '11 at 16:19
  • 1
    @kernel no. that was what i meant in the last paragraph – Michael Lowman Jul 14 '11 at 16:21
  • I think `{a,b}` is invalid in itself,as `ll {ucp.h}` fails when `ucp.h` DO exist. – kernel Jul 14 '11 at 16:33
  • @kernel let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/812/discussion-between-michael-lowman-and-kernel) – Michael Lowman Jul 14 '11 at 16:35
  • How to exclude directories from the result set of `find . -regextype posix-extended -regex '.*\.(c|h|cc)'`? – kernel Aug 04 '11 at 13:23
  • @kernel you should try reading the `find` man page, there are many options. the one you want to add is `-type f`, or `! -type d`. The difference between posix-extended regexes and emacs regexes mostly have to do with which characters need to be escaped. both my regex and @Iain's will work. To learn about POSIX regexes (a standard) try `man 7 regex`. – Michael Lowman Aug 04 '11 at 14:00
  • Seems I can't use `-type f` together with `-regextype posix-extended -regex '.*\.(c|h|cc)'` – kernel Aug 04 '11 at 23:04
  • @kernel I don't know why not; `find . -type f -regextype posix-extended -regex '.*\.(c|h|cc)'` works fine for me. if you really have issues, you should post more information rather than simply saying it doesn't work. and this sort of back-and-forth in comments is discouraged; better to do so in chat and keep comments to things that directly answer your original question. if you have further questions, ask a new question. – Michael Lowman Aug 05 '11 at 01:29
  • Don't you get this warning? `find: warning: you have specified the -regextype option after a non-option argument -type, but options are not positional (-regextype affects tests specified before it as well as those specified after it). Please specify options before other arguments.` – kernel Aug 05 '11 at 12:40
  • no, but that message is telling you to place options that don't affect matching (like `-regextype`) before matching commands (`-type` and `-regex`). Did you try modifying the command to meet those requirements? (That would be `find . -regextype posix-extended -type f -regex '.*\.(c|h|cc)'`). And no one's stopping you from using @Iain's. Seriously, I have no idea what possible reason you could have for not just using `-o`. It'll probably be faster; the POSIX regex engine isn't the best. And please, read the whole `find` manual. You may find it answers more of your questions than you think. – Michael Lowman Aug 05 '11 at 13:22
3

If you really want to use a regex then

 find -regex "\(.*\.[hc]\|.*\.cc\)"

should do the trick but the more normal way to do this is to use -o as already demonstrated.

user9517
  • 114,104
  • 20
  • 206
  • 289