Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question
add comment

2 Answers 2

up vote 4 down vote accepted

Try doing this :

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

Same thing with ack :

ack -rl '^#!/.*python' .
share|improve this answer
4  
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. –  Stéphane Chazelas Feb 25 '13 at 21:56
add comment

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
share|improve this answer
1  
+1, but the last command matches empty files as well. –  l0b0 Feb 28 '13 at 10:30
    
Good point @l0b0. Updated. –  Stéphane Chazelas Feb 28 '13 at 10:44
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.