Trouver tous les fichiers avec un Shebang Python

9

J'essaie d'exécuter une vérification PEP8 contre une grande arborescence source. L'arbre est composé d'un mélange de fichiers dans différentes langues. L'idée est de vérifier tous les scripts Python sans avoir à les lister explicitement. La majorité de ces fichiers n'ont pas réellement d' .pyextension. Existe-t-il un moyen simple de trouver tous les fichiers contenant le mot Python dans le shebang ou de trouver tous les fichiers qui seraient exécutés avec Python lors de leur exécution?

Marco Ceppi
la source

Réponses:

7

Essayez de faire ceci:

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

Même chose avec ack :

ack -rl '^#!/.*python' .
Gilles Quenot
la source
5
Notez que, même grep -ls'il arrête de lire un fichier dès qu'il trouve une correspondance, pour les fichiers sans correspondance, il lit l'intégralité du fichier. Il trouverait également des correspondances au milieu des fichiers, donc par exemple, il pourrait correspondre à un sharfichier contenant des scripts python.
Stéphane Chazelas
14

Avec GNU, ou FreeBSD ou NetBSD ou OpenBSD (et éventuellement d'autres) awk:

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

Ne regarderait que la première ligne de chaque fichier et exécuterait aussi peu awkque nécessaire.

La nextfiledéclaration ci-dessus n'est pas standard mais se trouve dans quelques implémentations, y compris GNU (qui est probablement d'où elle provient).

Bien que le code ci-dessus semble également fonctionner dans d'autres implémentations, l' nextfileinstruction n'y ferait rien (serait reconnue comme une expression consistant en une nextfilevariable non définie ), ce qui signifierait que tous les fichiers seraient lus entièrement et que le nom de fichier serait être imprimé pour chaque ligne correspondante.

Si vos awksupports FNR(comme les awks POSIX le font mais pas l'original awk, donc Solaris /usr/xpg4/bin/awket non /usr/bin/awk) et non nextfile, vous pouvez l'écrire:

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

Ce qui fonctionnerait toujours aussi peu awkque possible mais lirait complètement les fichiers.

Une autre alternative pour éviter de lire les fichiers en entier et qui fonctionnerait avec tous awket findqui signifierait en exécuter un awkpar fichier serait:

find . -type f -exec awk '
  /^#!.*python/{r=1};{exit}
  END {exit(1-r)}' {} \; -print
Stéphane Chazelas
la source
1
+1, mais la dernière commande correspond également aux fichiers vides.
l0b0
Bon point @ l0b0. Mise à jour.
Stéphane Chazelas