Encuentra todos los archivos con un Python Shebang

9

Estoy tratando de ejecutar una verificación PEP8 contra un gran árbol fuente. El árbol está compuesto por una mezcla de archivos en varios idiomas. La idea es verificar todos los scripts de Python sin tener que enumerarlos explícitamente. La mayoría de estos archivos en realidad no tienen una .pyextensión. ¿Hay una manera simple de encontrar todos los archivos con la palabra Python en el shebang o encontrar todos los archivos que se ejecutarían con Python cuando se ejecuten?

Marco Ceppi
fuente

Respuestas:

7

Intenta hacer esto:

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

Lo mismo con ack :

ack -rl '^#!/.*python' .
Gilles Quenot
fuente
55
Tenga en cuenta que si grep -lbien dejaría de leer un archivo tan pronto como encuentre una coincidencia, para los archivos sin coincidencia, leería todo el archivo. También encontraría coincidencias en el medio de los archivos, por lo que, por ejemplo, podría coincidir en un shararchivo que contiene scripts de Python.
Stéphane Chazelas
14

Con GNU, o FreeBSD o NetBSD u OpenBSD (y potencialmente otros) awk:

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

Solo miraría la primera línea de cada archivo y correría tan pocos awkcomo sea necesario.

La nextfiledeclaración anterior no es estándar, pero se encuentra en algunas implementaciones, incluida la GNU (que probablemente es de donde se originó).

Si bien el código anterior también parece funcionar en otras implementaciones, la nextfiledeclaración no haría nada allí (se reconocería como una expresión que consiste en una nextfilevariable no establecida), por lo que eso significaría que todos los archivos se leerían completamente y el nombre de archivo sería Se imprimirá para cada línea coincidente.

Si sus awksoportes FNR(como POSIX awks lo hacen pero no el original awk, así que en Solaris /usr/xpg4/bin/awky no /usr/bin/awk) y no nextfile, puede escribirlo:

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

Que aún se ejecutaría la menor cantidad de awksegundos posible, pero leería los archivos por completo.

Otra alternativa para evitar leer los archivos por completo y que funcionaría con todos awky findsignificaría ejecutar uno awkpor archivo sería:

find . -type f -exec awk '
  /^#!.*python/{r=1};{exit}
  END {exit(1-r)}' {} \; -print
Stéphane Chazelas
fuente
1
+1, pero el último comando también coincide con los archivos vacíos.
l0b0
Buen punto @ l0b0. Actualizado.
Stéphane Chazelas