When you issue a command on the command line, special characters are seen first by the shell, and then by the program; therefore, unquoted metacharacters are interpreted by the shell for filename expansion. The command:
$ grep [A-Z]* chap[12]
can, for example, be transformed by the shell into:
$ grep Array.c Bug.c Comp.c chap1 chap2
and can then try to find the pattern Array.c in files Bug.c , Comp.c , chap1 , and chap2 . To bypass the shell and pass the special characters to grep , use quotes:
$ grep "[A-Z]*" chap[12]
Double quotes suffice in most cases, but single quotes are the safest bet.
Note also that in pattern matching, ? matches zero or one instance of a regular expression; in filename expansion, ? matches a single character.