SaltyCrane Blog —  Notes on Python and web development on Ubuntu Linux

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:    for i in xrange(len(dol[keylist[0]])):            for i in xrange(len(dol[keylist[0]]))]     for i in xrange(len(locols[0])):         for j in xrange(len(keylist)):    return [dict([(keylist[j], locols[j][i]) for j in xrange(len(keylist))])            for i in xrange(len(locols[0]))]        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.

3 Comments — feed icon Comments feed for this post

#1 omkar commented on 2009-11-22:

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 2011-08-25:

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

#3 Kirubakaran commented on 2013-06-09:

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'"

Post a comment

Required, but not displayed

Format using Markdown. (No HTML.)
  • Code blocks: prefix each line by at least 4 spaces or 1 tab (and a blank line before and after)
  • Code span: surround with backticks
  • Blockquotes: prefix lines to be quoted with >
  • Links: <URL>
  • Links w/ description: [description](URL)
Created with Django and Bootstrap | Hosted by Linode