Q:

Begin a glob with an exclude pattern

I am trying to tweak some completion. Suppose I have:
$ ls
bar.baz  foo_bar.baz  foo.bar

If I want completion to match all files that don't end in baz:
$ shopt|grep extglob
extglob         on
$ compgen -G "*.!(baz)"
foo.bar

The exclude glob works as expected. But if I want all files that don't start with foo:
$ compgen -G "!(foo)*"
bar.baz
foo.bar
foo_bar.baz

All the files still match. Presumably this is because the * can still expand to match foo. Is there a glob trick to use exclusion followed by *?
As Janis pointed out, excluding foo needs to be !(foo*), but the actual use case is to also match on an extension, so the glob needs to be generally of the form !(foo*)*.bar (which still fails to exclude "foo" prefixes).

A:

You have to include the * in the negation, e.g.:
ls !(foo*)

Edit (to clarify): The requested [extended] globbing pattern is !(foo*). If used with the command compgen the call would be, e.g.:
compgen -G "!(foo*)"

You need quotes to pass the pattern to the command compgen unexpanded.
Edit (after question change): For your complete pattern in your edited question try one of @(!(foo*)|*bar) or @(!(bar*)|*foo). (See my comment below if that isn't what you expect.)

