Encontre todos os arquivos com um Python Shebang

9

Estou tentando executar uma verificação do PEP8 em uma grande árvore de origem. A árvore é composta de uma mistura de arquivos em vários idiomas. A idéia é verificar todos os scripts Python sem precisar listá-los explicitamente. A maioria desses arquivos não tem .pyextensão. Existe uma maneira simples de encontrar todos os arquivos com a palavra Python no shebang ou encontrar todos os arquivos que seriam executados com o Python quando executados?

Marco Ceppi
fonte

Respostas:

7

Tente fazer isso:

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

A mesma coisa com ack :

ack -rl '^#!/.*python' .
Gilles Quenot
fonte
5
Observe que, embora grep -lpare de ler um arquivo assim que encontrar uma correspondência, para arquivos sem correspondência, ele lerá o arquivo inteiro. Ele também encontraria correspondências no meio dos arquivos; portanto, poderia corresponder a um shararquivo que contém scripts python.
Stéphane Chazelas
14

Com o GNU, ou FreeBSD ou NetBSD ou OpenBSD (e potencialmente outros) awk:

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

Observaria apenas a primeira linha de cada arquivo e executaria o número de awksegundos que fosse necessário.

A nextfiledeclaração acima não é padrão, mas é encontrada em algumas implementações, incluindo a GNU (que provavelmente é de onde se originou).

Embora o código acima pareça funcionar em outras implementações também, a nextfileinstrução não faria nada lá (seria reconhecida como uma expressão que consiste em uma nextfilevariável não definida ), o que significa que todos os arquivos seriam lidos completamente e o nome do arquivo ser impresso para cada linha correspondente.

Se os seus awksuportes FNR(como os POSIX awks, mas não o original awk, assim como no Solaris /usr/xpg4/bin/awke não /usr/bin/awk) e não nextfile, você pode escrevê-lo:

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

O que ainda executaria o mínimo de awks possível, mas leria os arquivos completamente.

Outra alternativa para evitar a leitura completa dos arquivos e que funcionaria com todos awke, findporém, significaria executar um awkpor arquivo:

find . -type f -exec awk '
  /^#!.*python/{r=1};{exit}
  END {exit(1-r)}' {} \; -print
Stéphane Chazelas
fonte
1
+1, mas o último comando também corresponde aos arquivos vazios.
L0b0
Bom ponto @ l0b0. Atualizada.
Stéphane Chazelas