macOS & Linux
BSD's find implementation on macOS is different from GNU find - this is compatible with both BSD and GNU find. Start with a globbing implementation, using -name and the -o for or - Put this function in your .bashrc file:
pyclean () {
find . -type f -name '*.py[co]' -delete -o -type d -name __pycache__ -delete
}
Then cd to the directory you want to recursively clean, and type pyclean.
GNU find-only
This is a GNU find, only (i.e. Linux) solution, but I feel it's a little nicer with the regex:
pyclean () {
find . -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
}
Any platform, using Python 3
On Windows, you probably don't even have find. You do, however, probably have Python 3, which starting in 3.4 has the convenient pathlib module:
python3 -Bc "import pathlib; [p.unlink() for p in pathlib.Path('.').rglob('*.py[co]')]"
python3 -Bc "import pathlib; [p.rmdir() for p in pathlib.Path('.').rglob('__pycache__')]"
The -B flag tells Python not to write .pyc files. (See also the PYTHONDONTWRITEBYTECODE environment variable.)
The above abuses list comprehensions for looping, but when using python -c, style is rather a secondary concern. Alternatively we could abuse (for example) __import__:
python3 -Bc "for p in __import__('pathlib').Path('.').rglob('*.py[co]'): p.unlink()"
python3 -Bc "for p in __import__('pathlib').Path('.').rglob('__pycache__'): p.rmdir()"
Critique of an answer
The top answer used to say:
find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
This would seem to be less efficient because it uses three processes. find takes a regular expression, so we don't need a separate invocation of grep. Similarly, it has -delete, so we don't need a separate invocation of rm —and contrary to a comment here, it will delete non-empty directories so long as they get emptied by virtue of the regular expression match.
From the xargs man page:
find /tmp -depth -name core -type f -delete
Find files named core in or below the directory /tmp and delete them,
but more efficiently than in the previous example (because we avoid
the need to use fork(2) and exec(2) to launch rm and we don't need
the extra xargs process).
export PYTHONPYCACHEPREFIX=/tmp/pycache.