How to use grep and find to search specific files



This is my OLD blog. I've copied this post over to my NEW blog at:

http://www.saltycrane.com/blog/2007/12/how-to-use-grep-and-find-to-search/

You should be redirected in 2 seconds.



I often use grep to search through the text of my files for search terms such as a variable or function name. For example, since xrange is being removed from Python 3000, I'd like to search for all the occurrences of xrange. Here is how to search all my Python files in the current directory:

$ grep --color "xrange" *.py

Which outputs something like:

dol2lol.py:    for i in xrange(len(dol[keylist[0]])):
dol2lol.py:            for i in xrange(len(dol[keylist[0]]))]
lol2lod.py:#     for i in xrange(len(locols[0])):
lol2lod.py:#         for j in xrange(len(keylist)):
lol2lod.py:    return [dict([(keylist[j], locols[j][i]) for j in xrange(len(keylist))])
lol2lod.py:            for i in xrange(len(locols[0]))]
table_modelview.py:        for row in xrange(nrows):

The above command only works for the current directory. If I want to recurse into subdirectories, I can use:

$ grep -r --color "xrange" .

However, this command often produces too many results because I cannot specify which files to search. To gain better control over which files are searched, I can use grep in combination with the find command. Here is an example which recurses into subdirectories and searches all my Python files for xrange. (I know it's hard to imagine when xrange would be inside anything other than a Python file, but hey, it's just an example.

$ find . -name '*.py' -exec grep --color 'xrange' {} +

Usually, using find with -exec is very slow and xargs is used to gain performance. However, thanks to the tip from Some notes about find, I used the + expression at the end of the commandline which avoids the fork/exec overhead, without using xargs.

As a final example, here is how I search for the text #define in all files in my current directory, excluding my backup files (*~, *.orig, *.bak). In this example, I don't want to recurse into directories, so I set -maxdepth to 1. Note, Some notes about find has some other options about limiting the depth portably, but this option worked for me. Note, this is similar to the command I use as my Emacs grep.

find . -maxdepth 1 ! -regex '.*~$' ! -regex '.*\.orig$' \
    ! -regex '.*\.bak$' -exec grep --color "#define" {} +

No comments:

About

This is my *OLD* blog. I've copied all of my posts and comments over to my NEW blog at:

http://www.saltycrane.com/blog/.

Please go there for my updated posts. I will leave this blog up for a short time, but eventually plan to delete it. Thanks for reading.