34

I've read Use grep --exclude/--include syntax to not grep through certain files
but in my CentOS6.4, when I do

grep --exclude=*.cmd ckim * -r 

I see lots of grepped lines from *.cmd files.
so it seems the exclude option is not working for me.
What is wrong?
of course I can do things like

grep ckim \`find . -name \*.c -print\` 

but I want to know why the grep doesn't work.

1
  • you need to include pattern parameter. Commented Jul 19, 2014 at 6:58

6 Answers 6

57

You can quote the pattern:

grep -r --exclude="*.cmd" "ckim" ./ 

PS. ./ is the current directory

Sign up to request clarification or add additional context in comments.

3 Comments

This won't give a significant difference unless the OP has set nullglob. --exclude=*.cmd is unlikely to match a single file and would remain as is as an argument. It's the right practice but it doesn't give the solution.
@konsolebox, I must admit I don't know much about nullglob but shopt says it's off and still works. Am I missing something?
It should work but even if unquoted it still would. I might be wrong with my assumption actually, and that your code may actually be able to help solve the issue - not because you're helping it prevent itself from expanding to a file, but because you help prevent it from becoming nullified when nullglob is enabled. Thanks to quoting, any kind of pathname expansion is prevented. I can't believe I really overlooked that part.
3

Use . as pathspec instead of *.

grep -r --exclude \*.cmd ckim . 

4 Comments

On my test here the command still works even if * is used. Explicit file arguments are still filtered.
@konsolebox: ACK with Ubuntu
I think . with -r is more clear and never cause unwanted behaviour of shell-expansion.
@konsolebox: ACK with RHEL7
1

you could also do something like this

grep -rn ckim * | grep -v '\.cmd' 

2 Comments

This has unwanted behaviour, imagine the line inside the file has something.cmd it will not display that line even if the filename does not contain \.cmd
Yes it has some unwanted behavior ... but there will be very much less possibility of ckim occurring with '.cmd' on the same line
1

I see lots of grepped lines from *.cmd files. So it seems the exclude option is not working for me.

There is a shell option called nullglob that controls the expansion of shell patterns when there is no matching file.


So, given the following environment:

sh$ touch f.cmd g.sh sh$ mkdir sub sh$ echo ckim > sub/h.cmd sh$ echo ckim > sub/i.cmd 

On my system (where nullglob is unset), the following command:

grep --exclude=*.cmd ckim * -r 

Is expanded ("understood") by the shell as:

grep --exclude=*.cmd ckim f.cmd g.sh sub -r 

That is, I will recursively (-r) search for the string skim starting with f.cmd, g.sh and sub but excluding any file matching the pattern '*.cmd'.

The result is:

# nullglob is unset sh$ grep --exclude=*.cmd ckim * -r sub/i.sh:ckim 

BUT if in your environment the option nullglob is set, the same command expands to:

grep ckim f.cmd g.sh sub -r 

Notice how the whole --exclude=... has disappeared. So the result is:

# nullglob is set sh$ grep --exclude=*.cmd ckim * -r sub/i.sh:ckim sub/h.cmd:ckim 

An now, for the explanation. When the shell encounters a glob pattern (i.e.: containing * or ? or a few more special characters), it expands it with the matching files. But if there is no matching files, it either let the pattern as it (if nullglob is not set) or replace it with "nothing" (if nullglob is set).

Here the pattern is --include=*.cmd (at whole since there is no space in there). In the unlikely event you have a file matching this pattern it would have been replaced. Otherwise it is either let "as it" or completely removed -- depending on nullglob.


You can easely display, set (-s) or unset (-u) the status of nullglob option of your current bash:

sh$ shopt nullglob nullglob on sh$ shopt -u nullglob sh$ shopt nullglob nullglob off sh$ shopt -s nullglob sh$ shopt nullglob nullglob on 

Comments

1

The shortest code for multiple files (note the DOT for files ending in '~') is:

grep -lr --exclude=*.{zip,bak,~} "Hello world!" world/* (wrong code) grep -lr --exclude=*{zip,bak,~} "Hello world!" world/* (correct code) 

ChatGPT can give you the wrong code for this specific case. The dot is not followed by '~', as in nycity.txt~

Comments

0

If you want to exclude certain files to grep from, you should use the -l option.

grep -l --exclude=*.cmd ckim * -r 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.