The shell performs glob expansion before it even thinks of invoking the command. Programs such as grep don't do anything to prevent globbing: they can't. You, as the caller of these programs, must tell the shell that you want to pass the special characters such as *
and ?
to the program, and not let the shell interpret them. You do that by putting them inside quotes:
grep -E 'ba(na)* split' *.txt
(look for ba split
, bana split
, etc., in all files called <something>.txt
) In this case, either single quotes or double quotes will do the trick. Between single quotes, the shell expands nothing. Between double quotes, $
, `
and \
are still interpreted. You can also protect a single character from shell expansion by preceding it with a backslash. It's not only wildcard characters that need to be protected; for example, above, the space in the pattern is in quotes so it's part of the argument to grep
and not an argument separator. Alternative ways to write the snippet above include
grep -E "ba(na)* split" *.txt
grep -E ba\(na\)\*\ split *.txt
With most shells, if an argument contains wildcards but the pattern doesn't match any file, the pattern is left unchanged and passed to the underlying command. So a command like
grep b[an]*a *.txt
has a different effect depending on what files are present on the system. If the current directory doesn't contain any file whose name begins with b
, the command searches the pattern b[an]*a
in the files whose name matches *.txt
. If the current directory contains files named baclava
, bnm
and hello.txt
, the command expands to grep baclava bnm hello.txt
, so it searches the pattern baclava
in the two files bnm
and hello.txt
. Needless to say, it's a bad idea to rely on this in scripts; on the command line it can occasionally save typing, but it's risky.
When you run ack .*
in a directory containing no dot file, the shell runs ack . ..
. The behavior of the ack
command is then to print out all non-empty lines (pattern .
: matches any one character) in all files under ..
(the parent of the current directory) recursively. Contrast with ack '.*'
, which searches the pattern .*
(which matches anything) in the current directory and its subdirectories (due to the behavior of ack
when you don't pass any filename argument).