SaltyCrane Blog — Notes on JavaScript and web development

How to use grep and find to search specific files

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" {} +

Using grep to exclude a pattern

If you want to find all the lines that DO NOT match a particular pattern, use the -v (or --invert-match) option to invert the match and select non-matching lines.

Comments


#1 omkar commented on :

hi, thnx for this. plz, give me solution for :: if i want to find files with 2nd letter 'i' and having extension as '.sh'. PLz plz....send me today only


#2 himanshu arora commented on :

thanx a tonne...it'd be a lot of help in reverse engineering a tool i'm currently working on...:D


#3 Kirubakaran commented on :

You could also use M-x grep-find, which conveniently gives you a find command template to which you can add the search string and "-name '*.py'"