Use grep --exclude/--include syntax to not grep th

2019-01-04 15:25发布

I'm looking for the string foo= in text files in a directory tree. It's on a common Linux machine, I have bash shell:

grep -ircl "foo=" *

In the directories are also many binary files which match "foo=". As these results are not relevant and slow down the search, I want grep to skip searching these files (mostly JPEG and PNG images). How would I do that?

I know there are the --exclude=PATTERN and --include=PATTERN options, but what is the pattern format? The man page of grep says:

--include=PATTERN     Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN     Recurse in directories skip file matching PATTERN.

Searching on grep include, grep include exclude, grep exclude and variants did not find anything relevant

If there's a better way of grepping only in certain files, I'm all for it; moving the offending files is not an option. I can't search only certain directories (the directory structure is a big mess, with everything everywhere). Also, I can't install anything, so I have to do with common tools (like grep or the suggested find).

22条回答
太酷不给撩
2楼-- · 2019-01-04 15:54

The suggested command:

grep -Ir --exclude="*\.svn*" "pattern" *

is conceptually wrong, because --exclude works on the basename. Put in other words, it will skip only the .svn in the current directory.

查看更多
贼婆χ
3楼-- · 2019-01-04 15:54

On CentOS 6.6/Grep 2.6.3, I have to use it like this:

grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"

Notice the lack of equal signs "=" (otherwise --include, --exclude, include-dir and --exclude-dir are ignored)

查看更多
Rolldiameter
4楼-- · 2019-01-04 15:56

If you are not averse to using find, I like its -prune feature:

find [directory] \
        -name "pattern_to_exclude" -prune \
     -o -name "another_pattern_to_exclude" -prune \
     -o -name "pattern_to_INCLUDE" -print0 \
| xargs -0 -I FILENAME grep -IR "pattern" FILENAME

On the first line, you specify the directory you want to search. . (current directory) is a valid path, for example.

On the 2nd and 3rd lines, use "*.png", "*.gif", "*.jpg", and so forth. Use as many of these -o -name "..." -prune constructs as you have patterns.

On the 4th line, you need another -o (it specifies "or" to find), the patterns you DO want, and you need either a -print or -print0 at the end of it. If you just want "everything else" that remains after pruning the *.gif, *.png, etc. images, then use -o -print0 and you're done with the 4th line.

Finally, on the 5th line is the pipe to xargs which takes each of those resulting files and stores them in a variable FILENAME. It then passes grep the -IR flags, the "pattern", and then FILENAME is expanded by xargs to become that list of filenames found by find.

For your particular question, the statement may look something like:

find . \
     -name "*.png" -prune \
     -o -name "*.gif" -prune \
     -o -name "*.svn" -prune \
     -o -print0 | xargs -0 -I FILES grep -IR "foo=" FILES

查看更多
在下西门庆
5楼-- · 2019-01-04 15:57

suitable for tcsh .alias file:

alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'

Took me a while to figure out that the {mm,m,h,cc,c} portion should NOT be inside quotes. ~Keith

查看更多
【Aperson】
6楼-- · 2019-01-04 15:58

In grep 2.5.1 you have to add this line to ~/.bashrc or ~/.bash profile

export GREP_OPTIONS="--exclude=\*.svn\*"
查看更多
Evening l夕情丶
7楼-- · 2019-01-04 15:59

If you just want to skip binary files, I suggest you look at the -I (upper case i) option. It ignores binary files. I regularly use the following command:

grep -rI --exclude-dir="\.svn" "pattern" *

It searches recursively, ignores binary files, and doesn't look inside Subversion hidden folders, for whatever pattern I want. I have it aliased as "grepsvn" on my box at work.

查看更多
登录 后发表回答