11

I'm trying to run a PEP8 check against a large source tree. The tree is comprised of a mix of files in various languages. The idea is to check all the Python scripts without having to explicitly list them. The majority of these files don't actually have a .py extension. Is there a simple way to find all files with the word Python in the shebang or find all files that would be run with Python when executed?

2 Answers 2

18

With GNU, or FreeBSD or NetBSD or OpenBSD (and potentially others) awk:

find . -type f -exec awk '
  /^#!.*python/{print FILENAME}
  {nextfile}' {} +

Would look only at the first line of each file and would run as few awks as necessary.

The nextfile statement above is not standard but is found in a few implementations including the GNU one (which is probably where it originated from).

While the code above would appear to work in other implementations as well, the nextfile statement would not do anything there (would be recognised as an expression consisting in an unset nextfile variable), so that would mean all the files would be read fully and the filename would be printed for every matching line.

If your awk supports FNR (like POSIX awks do but not the original awk, so on Solaris /usr/xpg4/bin/awk and not /usr/bin/awk) and not nextfile, you can write it:

find . -type f -exec awk 'FNR == 1 && /^#!.*python/{print FILENAME}' {} +

Which would still run as few awks as possible but would read the files fully.

Another alternative to avoid reading the files fully and that would work with every awk and find but would mean running one awk per file would be:

find . -type f -exec awk '
  /^#!.*python/{r=1};{exit}
  END {exit(1-r)}' {} \; -print
2
  • 1
    +1, but the last command matches empty files as well.
    – l0b0
    Commented Feb 28, 2013 at 10:30
  • Good point @l0b0. Updated. Commented Feb 28, 2013 at 10:44
8

Try doing this :

grep -rl '^#!/.*python' .

Same thing with ack :

ack -rl '^#!/.*python' .
1
  • 7
    Note that while grep -l would stop reading a file as soon as it finds a match, for files with no match, it would read the whole file. It would also find matches in the middle of files, so for instance it could match on a shar file that contains python scripts. Commented Feb 25, 2013 at 21:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .