我如何统计整个系统中的所有 python 和 shell 脚本?
答案1
在没有更具体的目标的情况下,无论你怎么做,这都是近似的,因为关于什么是 shell 脚本和什么是 Python 脚本存在歧义。这并不会让问题变得太不明确,只要你想要的是近似值.并且可以得到一个很好的近似值。
鉴于此,我建议使用此命令列出 shell 和 Python 脚本:
find . -type f -executable -exec file {} + | grep -Ei '(python|shell) script,'
如果输出看起来合理,符合您的需求,您可以再次运行它,并进行修改以计算结果数量:
find . -type f -executable -exec file {} + | grep -Ei '(python|shell) script,' | wc -l
您可能会收到一些“权限被拒绝”错误。没关系。我不建议尝试隐藏这些错误消息,因为您应该阅读或至少浏览它们以查看是否看起来您无法访问您感兴趣的任何文件或位置。如果您确实想要,您可以find
以 root 身份运行该命令。sudo
-type f
使其仅查找常规文件。通常,最好使用-xtype f
包含解析为常规文件的符号链接,但在这种情况下,这会导致计数过高。-executable
使其仅查找运行 的用户可执行的文件find
。查看不可执行文件以查看它们是否看起来是 shell 或 Python 脚本将使命令花费更长的时间。这样,您还可能会得到更多的误报,因为不可执行的文件可能是“库”而不是脚本,即它们可能由 shell 命令组成,旨在用于使用或将 shell 脚本作为源.
,source
或者它们可能是 Python 模块,可以使用import
或from
将 Python 程序导入。(您可能认为这不会发生,因为此类文件通常没有舍邦,但find
看起来不止是一桩事。)但是,-executable
如果你愿意,你可以省略——并且如果你愿意等待因为您的命令尝试打开并读取系统上每个常规文件的开头。-exec ... +
运行命令...
,将找到的文件作为其命令行参数。它会根据需要多次运行该命令以处理所有文件。通常,这仅是一次;对于整个系统上的所有可执行文件,它可能不止一次,但比对每个文件运行一次(如-exec ... \;
所愿)的次数要少得多。即使对于相同数量的文件,运行命令较少的次数往往比运行更多次要快得多,因为相关开销较低。- 该
file
命令查看文件的开头,并猜测它是什么类型的文件(通常非常准确)。它以两列格式输出,左侧是路径或文件名,右侧是内容摘要种类文件的右侧显示。 - 该
grep
命令会过滤其输入并仅输出不区分大小写 (-i
) 匹配的行扩展正则表达式(-E
)(python|shell) script,
。这些行包含文本python script,
、shell script,
或任何大小写变体。文件find
标识为这些类型的脚本将显示此信息。 wc -l
,出现在上面显示的两个命令中的第二个命令中,用于计数行数。
如图所示,该技术完全不适合许多涉及辨别某人拥有什么类型的文件的任务。原因是文件python script,
名称中可以包含类似文本,以及名称中的换行符,这会导致输出file
不为每行一个。对这些事情进行解释通常很重要,甚至是至关重要的,而且这是可以做到的。但是,在这种情况下,您只是在进行估算(由于问题本身的模糊性),而且看起来您并没有直接根据结果重命名、修改、删除甚至创建任何东西,所以我认为没有必要担心这一点。如果您最终对此进行迭代并更严格地定义问题,那么解决这个问题可能是值得的。
请注意,在一种主要情况下,您可能希望将不可执行文件视为脚本:如果您有许多 Python 脚本从 Windows 等系统移植过来,而这些脚本未标记为可执行。在这种情况下,您可以搜索.py
文件,但请注意,其中许多文件可能是 Python 模块而不是 Python 脚本。如果遵循了将 hashbang 放在脚本顶部的良好 Python 做法(这在 Windows 中也很有用,因为py.exe
可以pyw.exe
识别它们,但不幸的是,它并不总是这样做),那么只查找 hashbang 而忽略文件是否可执行的技术可能更适合您的需求。
还有一种次要但重要的情况,您可能希望将不可执行文件视为任何类型的脚本——或者更准确地说,您可能希望以不同的方式测试可执行性。如果您安装了驱动器noexec
,那么它上面的任何文件都不会通过find
测试-executable
。请注意,这与以find
无权执行某些文件的用户身份运行是不同的问题——就像以无权查看某些目录的用户身份运行它的问题一样,这可以通过以具有足够权限的用户身份运行它来解决。
这个问题,正如你所说,是不寻常的——通常人们会希望找到特定语言或紧密相关的语言小家族的文字。但为了方便未来的读者,请注意,只需对上述命令稍作修改,即可在一个可能很大的目录中找到所有(例如)shell 脚本。(对于在WinEunuuchs2Unix 的答案——对此它也是有用的。)
例如,查找当前目录中的所有 shell 脚本:
find . -type f -executable -exec file {} + | grep -Fi 'shell script,'
答案2
快速概览
以下是有关如何操作的指南。
$ for f in * ; do file "$f" ; done
aptfielout: ASCII text, with very long lines
aptfilein: ASCII text, with very long lines
aptfileout: ASCII text
aptfileparse.sh: Bourne-Again shell script, ASCII text executable, with very long lines
aptfileparse.sh~: ASCII text, with very long lines
calc.py: Python script, UTF-8 Unicode text executable
catall.sh: Bourne-Again shell script, ASCII text executable
删除所有未提及“Bourne-Again shell 脚本”或“Python 脚本”的文件。将 POSIX shell 脚本添加到列表中:
$ file /bin/zgrep
/bin/zgrep: POSIX shell script, ASCII text executable
完整的答案
/$ time find * -type f -print0 2>/dev/null | xargs -0 -P 8 file | \
sed 's/.*: //g' | sed 's/^ *//g' | \
grep -Eio 'shell script,|Python script,' | sort | uniq -c
19151 Python script,
127 python script,
18420 shell script,
real 16m14.939s
user 54m7.355s
sys 2m33.238s
从根目录(/
)开始find
,所有文件和管道xargs
以零字节终止的名称传递给命令。
该xargs
命令并行运行,最大限度地利用所有 8 个 CPU 来加快处理速度。每个并行进程都会调用该file
命令,该命令会获取文件描述,如上一节所示。
该grep
命令选择shell脚本和python脚本。
该sort
命令将shell脚本排序在一起,将python脚本排序在一起。
该uniq
命令计算每个组的出现次数。
有趣的事实
你可以真正地让你的系统同时运行所有 8 个 CPU(在我的情况下):
Linux 的魅力得以彰显,因为其他工作(例如屏幕录像机制作.gif
和在第三台显示器(大屏幕电视)上运行的视频)继续正常运行。Linux 不会让命令xargs file
拖慢系统。