Znajdź wszystkie pliki za pomocą Python Shebang

9

Próbuję uruchomić test PEP8 na dużym drzewie źródeł. Drzewo składa się z mieszanki plików w różnych językach. Chodzi o to, aby sprawdzić wszystkie skrypty Pythona bez konieczności ich jawnego wyświetlania. Większość tych plików nie ma tak naprawdę .pyrozszerzenia. Czy istnieje prosty sposób na znalezienie wszystkich plików ze słowem Python w shebang lub znalezienie wszystkich plików, które byłyby uruchamiane przy użyciu Pythona po uruchomieniu?

Marco Ceppi
źródło

Odpowiedzi:

7

Spróbuj to zrobić:

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

To samo z potwierdzeniem :

ack -rl '^#!/.*python' .
Gilles Quenot
źródło
5
Zauważ, że chociaż grep -lprzestanie czytać plik, gdy tylko znajdzie dopasowanie, w przypadku plików bez dopasowania, odczyta cały plik. Znajduje również dopasowania w środku plików, więc na przykład może pasować do sharpliku zawierającego skrypty python.
Stéphane Chazelas,
14

W przypadku GNU, FreeBSD lub NetBSD lub OpenBSD (i potencjalnie innych) awk:

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

Spojrzałby tylko na pierwszą linię każdego pliku i uruchomiłby tak mało awks, jak to konieczne.

Powyższe nextfilestwierdzenie nie jest standardowe, ale można je znaleźć w kilku implementacjach, w tym w GNU (prawdopodobnie z tego, skąd pochodzi).

Chociaż powyższy kod wydaje się działać również w innych implementacjach, nextfileinstrukcja nic by tam nie zrobiła (byłaby rozpoznawana jako wyrażenie składające się z nextfilezmiennej nieustawionej ), co oznaczałoby, że wszystkie pliki zostałyby odczytane w całości, a nazwa pliku być drukowane dla każdej pasującej linii.

Jeśli twoje awkwsparcie FNR(takie jak POSIX-owe wersje robią, ale nie oryginalne awk, więc w Solarisie /usr/xpg4/bin/awki nie /usr/bin/awk) i nie nextfile, możesz to napisać:

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

Co nadal działałoby tak mało awkjak to możliwe, ale w pełni odczytywało pliki.

Inną alternatywą, aby uniknąć czytania plików całkowicie i że będzie współpracować z każdym awk, a findjednak oznaczałoby uruchomiony jeden awkna plik będzie:

find . -type f -exec awk '
  /^#!.*python/{r=1};{exit}
  END {exit(1-r)}' {} \; -print
Stéphane Chazelas
źródło
1
+1, ale ostatnie polecenie również pasuje do pustych plików.
l0b0
Dobry punkt @ 10b0. Zaktualizowano
Stéphane Chazelas