使用 Python Shebang 查找所有文件

Mar*_*ppi 10 search shell-script text-processing

我正在尝试针对大型源代码树运行 PEP8 检查。该树由各种语言的文件混合组成。这个想法是检查所有 Python 脚本,而不必明确列出它们。大多数这些文件实际上没有.py扩展名。有没有一种简单的方法可以在 shebang 中找到所有带有 Python 一词的文件,或者找到所有在执行时会用 Python 运行的文件?

Sté*_*las 16

使用 GNU、FreeBSD、NetBSD 或 OpenBSD(以及其他可能的)awk

find . -type f -exec awk '
  /^#!.*python/{print FILENAME}
  {nextfile}' {} +
Run Code Online (Sandbox Code Playgroud)

将只查看每个文件的第一行,并awk根据需要运行尽可能少的s。

nextfile上面的语句不是标准的,但可以在包括 GNU 在内的一些实现中找到(这可能是它的起源)。

虽然上面的代码似乎也适用于其他实现,但该nextfile语句不会在那里做任何事情(将被识别为包含未设置nextfile变量的表达式),因此这意味着将完全读取所有文件并且文件名将为每个匹配的行打印。

如果您的awk支持FNR(如 POSIX awks支持但不是原始的awk,所以在 Solaris 上/usr/xpg4/bin/awk而不是/usr/bin/awk)而不是nextfile,您可以编写它:

find . -type f -exec awk 'FNR == 1 && /^#!.*python/{print FILENAME}' {} +
Run Code Online (Sandbox Code Playgroud)

哪个仍然会运行尽可能少的awks 但会完全读取文件。

另一种方法,以避免完全读取文件,并会与每一个工作awkfind,而且意味着运行一个awk每个文件将是:

find . -type f -exec awk '
  /^#!.*python/{r=1};{exit}
  END {exit(1-r)}' {} \; -print
Run Code Online (Sandbox Code Playgroud)


Gil*_*not 7

尝试这样做:

grep -rl '^#!/.*python' .
Run Code Online (Sandbox Code Playgroud)

ack相同:

ack -rl '^#!/.*python' .
Run Code Online (Sandbox Code Playgroud)

  • 请注意,虽然 `grep -l` 会在找到匹配项后立即停止读取文件,但对于没有匹配项的文件,它会读取整个文件。它还会在文件中间找到匹配项,因此例如它可以匹配包含 python 脚本的 `shar` 文件。 (6认同)