How do I write a bash alias/function to grep all files in all subdirectories for a string? How do I write a bash alias/function to grep all files in all subdirectories for a string? shell shell

How do I write a bash alias/function to grep all files in all subdirectories for a string?


If you don't want to create an entire script for this, you can do it with just a shell function:

findpy() { find . -name '*.py' -exec grep -nHr "$1" {} \; ; }

...but then you may have to define it in both ~/.bashrc and ~/.bash_profile, so it gets defined for both login and interactive shells (see the INVOCATION section of bash's man page).


All the "find ... -exec" solutions above are OK in the sense that they work, but they are horribly inefficient and will be extremely slow for large trees. The reason is that they launch a new process for every single *.py file. Instead, use xargs(1), and run grep only on files (not directories):

#! /bin/shfind . -name \*.py -type f | xargs grep -nHr "$1"

For example:

$ time sh -c 'find . -name \*.cpp -type f -exec grep foo {} \; >/dev/null'real    0m3.747s$ time sh -c 'find . -name \*.cpp -type f | xargs grep foo >/dev/null'real    0m0.278s


On a side note, you should take a look at Ack for what you are doing. It is designed as a replacement for Grep written in Perl. Filtering files based on the target language or ignoring .svn directories and the like.

Example (snippet from Trac source):

$ ack --python foo ./mysourceticket/tests/wikisyntax.py139:milestone:foo144:<a class="missing milestone" href="/milestone/foo" rel="nofollow">milestone:foo</a>ticket/tests/conversion.py34:        ticket['foo'] = 'This is a custom field'ticket/query.py239:        count_sql = 'SELECT COUNT(*) FROM (' + sql + ') AS foo'