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'