Temukan semua file dengan Python Shebang

9

Saya mencoba menjalankan pemeriksaan PEP8 terhadap pohon sumber besar. Pohon itu terdiri dari campuran file dalam berbagai bahasa. Idenya adalah untuk memeriksa semua skrip Python tanpa harus secara eksplisit mencantumkannya. Sebagian besar file-file ini sebenarnya tidak memiliki .pyekstensi. Apakah ada cara sederhana untuk menemukan semua file dengan kata Python di shebang atau menemukan semua file yang akan dijalankan dengan Python ketika dieksekusi?

Marco Ceppi
sumber

Jawaban:

7

Coba lakukan ini:

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

Hal yang sama dengan ack :

ack -rl '^#!/.*python' .
Gilles Quenot
sumber
5
Perhatikan bahwa sementara grep -lakan berhenti membaca file segera setelah menemukan kecocokan, untuk file tanpa kecocokan, itu akan membaca seluruh file. Itu juga akan menemukan kecocokan di tengah file, jadi misalnya itu bisa cocok dengan sharfile yang berisi skrip python.
Stéphane Chazelas
14

Dengan GNU, atau FreeBSD atau NetBSD atau OpenBSD (dan yang lainnya) awk:

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

Akan terlihat hanya pada baris pertama setiap file dan akan berjalan sesedikit yang awkdiperlukan.

The nextfilepernyataan di atas tidak standar tetapi ditemukan dalam beberapa implementasi termasuk salah satu GNU (yang mungkin di mana ia berasal dari).

Sementara kode di atas akan tampak berfungsi dalam implementasi lain juga, nextfilepernyataan itu tidak akan melakukan apa pun di sana (akan dikenali sebagai ekspresi yang terdiri dari nextfilevariabel yang tidak disetel ), sehingga itu berarti semua file akan dibaca sepenuhnya dan nama file akan dicetak untuk setiap baris yang cocok.

Jika awkdukungan Anda FNR(seperti POSIX awks melakukan tetapi bukan yang asli awk, jadi pada Solaris /usr/xpg4/bin/awkdan bukan /usr/bin/awk) dan tidak nextfile, Anda dapat menulisnya:

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

Yang masih akan berjalan sesedikit awkmungkin tetapi akan membaca file sepenuhnya.

Alternatif lain untuk menghindari membaca file sepenuhnya dan itu akan bekerja dengan setiap awkdan findtetapi berarti menjalankan satu awkper file adalah:

find . -type f -exec awk '
  /^#!.*python/{r=1};{exit}
  END {exit(1-r)}' {} \; -print
Stéphane Chazelas
sumber
1
+1, tetapi perintah terakhir juga cocok dengan file kosong.
l0b0
Poin bagus @ l0b0. Diperbarui.
Stéphane Chazelas