That's the trick: command doesn't know, it's the shell that does the job
Consider for example grep 'abc' *.txt
. If we run trace of system calls, you will see something like this:
bash-4.3$ strace -e trace=execve grep "abc" *.txt > /dev/null
execve("/bin/grep", ["grep", "abc", "ADDA_converters.txt", "after.txt", "altera_license.txt", "altera.txt", "ANALOG_DIGITAL_NOTES.txt", "androiddev.txt", "answer2.txt", "answer.txt", "ANSWER.txt", "ascii.txt", "askubuntu-profile.txt", "AskUbuntu_Translators.txt", "a.txt", "bash_result.txt", ...], [/* 80 vars */]) = 0
+++ exited with 0 +++
The shell expanded *.txt
into all filenames in current directory that end with .txt
extension. So effectively, your shell translates the grep 'abc' *.txt
command into grep 'abc' file1.txt file2.txt file3.txt . . .
. Thus, your second assumption is correct.
First assumption is not correct - programs have no way of detecting glob. It is possible to pass *
as string argument to command, but it's the command's job to decide what to do with it then. Filename expansion, however, is property of your respective shell as I've already mentioned.
However, this only works because grep accepts multiple files at the end. It is possible that another command would only allow 1 file to be passed in.
Exactly right ! Programs don't limit the number of acceptable command-line arguments (for instance , in C that's array of strings const char *args[]
and in python sys.argv[]
), but they can detect the length of that array or whether or not something unexpected is in wrong array position. grep
doesn't do that, and accepts multiple files, which is by design.
On side note , improper quoting coupled with globbing with grep can sometimes be a problem. Consider this:
bash-4.3$ echo "one two" | strace -e trace=execve grep *est*
execve("/bin/grep", ["grep", "self_test.sh", "test.wxg"], [/* 80 vars */]) = 0
+++ exited with 1 +++
Unprepared user would expect that grep will match any line with est
letters in it coming from pipe, but instead shell's filename expansion twisted everyting around. I've seen this happen a lot with people who do ps aux | grep shell_script_name.sh
, and they expect to find their process running, but because they ran command from same directory where script was, shell's filename expansion made grep
command to look completely different behind the scenes from what user expected.
Proper way would be to use single quotes:
bash-4.3$ echo "one two" | strace -e trace=execve grep '*est*'
execve("/bin/grep", ["grep", "*est*"], [/* 80 vars */]) = 0
+++ exited with 1 +++
Best Answer
Don't use
*
for this. Usegrep 'ki' trial_file.txt
orgrep -F 'ki' trial_file.txt
.Unless you pass it the
-x
/--line-regex
option,grep
will return lines that contain a match anywhere, even if the whole line isn't a match. So all you have to do is match part of the line. You don't have to do anything special to indicate there may be more characters.In a regular expression,
*
means "zero or more of the previous item." This is an entirely different from its meaning in shell pathname expansion (see also this article,man 7 glob
, and this section). So, for example:ax*b
matchesa
, followed by any number ofx
es (even none), followed byb
:ab
,axb
,axxb
,axxxb
, ...a[xz]*b
matchesa
followed by any number of characters where each isx
orz
, followed byb
:ab
,axb
,azb
,axxb
,axzb
,azxb
,azzb
,axxxb
, ...a(xyz)*b
matchesa
, followed zero or more occurrences of the stringxyz
, followed byb
:ab
,axyzb
,axyzxyzb
,axyzxyzxyzb
, ...In this case, it seems like you're just searching for text. You don't need to use any regular expression metacharacters like
.
,*
, or\
that have special meanings. That's why I suggest passing the-F
flag, which makesgrep
search for "fixed strings" rather than performing regular expression matching.If, however, you only want to match starting at the beginning of the line, then you do want to use a regular expression metacharacter:
^
, as mjb2kmn suggests. This anchors your match to the start of the line. In that case you would rungrep '^ki' trial_file.txt
.For more information on the options
grep
supports, seeman grep
and the GNU Grep manual.Although in general I suggest enclosing regular expressions in
'
'
quotes, in this case no quoting is necessary because the shell does not perform any expansions onki
or^ki
before passing them togrep
.