目录中文件类型的递归统计?


65

我做了一个网站抓取一个转换项目。我想对其中的文件类型进行一些统计-例如400个.html文件,100个.gif等。执行此操作的简单方法是什么?它必须是递归的。

编辑:使用maxschelpzig发布的脚本,由于我抓取的网站的体系结构,我遇到了一些问题。有些文件的名称*.php?blah=blah&foo=bar带有各种参数,因此将它们全部视为唯一文件。因此*.php*,可以这么说,解决方案需要考虑为同一类型。

Answers:


97

您可以使用finduniq,例如:

$ find . -type f | sed 's/.*\.//' | sort | uniq -c
   16 avi
   29 jpg
  136 mp3
    3 mp4

命令说明

  • find 递归打印所有文件名
  • sed 从每个文件名删除前缀,直到文件扩展名
  • uniq 假设输入已排序
    • -c 进行计数(如直方图)。

我有一个类似的脚本。简单快捷。
Rufo El Magufo 2011年

有些文件的名称*.php?blah=blah&foo=bar带有各种参数,因此将它们全部视为唯一文件。我如何修改它以寻找*.php*
user394 2011年

3
您可以尝试使用其他sed表达式,例如sed 's/^.*\(\.[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]\).*$/\1/'
maxschlepzig

感谢您抽出宝贵的时间来解释每个部分的作用。关于相似主题的许多答案都跳过了这一部分。/学习钓鱼
-MechEthan 2013年

1
@ bela83,prune变体依赖于短路评估 -因此,我的第一个版本find -name '.*' -prune -o -type f -print评估如下:如果目录条目匹配,.*则对其进行修剪,否则,如果它是文件,则进行打印。由于.*还匹配.,即CWD,因此将删除所有内容,即find甚至都不会下降到第一个目录中。也许是2岁的find行为有所不同-或那只是我的疏忽。无论如何,find -name '.*' -not -name . -prune -o -type f -print解决此问题。
maxschlepzig 2015年

7

使用zsh:

print -rl -- **/?*.*(D.:e) | uniq -c |sort -n

模式 **/?*.*以递归方式匹配当前目录及其子目录中所有具有扩展名的文件。该水珠预选赛 Dzsh遍历甚至隐藏目录,并考虑隐藏文件,.只选择常规文件。该历史修改将仅保留文件扩展名。print -rl每行打印一个匹配项。uniq -c对连续的相同项目进行计数(全局结果已排序)。最后一个sort按使用次数对扩展名进行排序的调用。


5

这种单线似乎是一个相当健壮的方法:

find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$/\1/p' | sort | uniq -c

find . -type f -printf '%f\n'打印树中的每个常规文件的基本名称,没有目录。消除不必担心可能有目录.的在他们在您的sed正则表达式。

sed -r -n 's/.+(\..*)$/\1/p'只有它的扩展取代了传入文件名。例如,.somefile.ext变为.ext。注意.+正则表达式中的首字母;这将导致任何匹配在扩展名之前至少需要一个字符.。这样可以防止像这样的文件名.gitignore被当作​​完全没有名称,并且扩展名“ .gitignore”可能就是您想要的。如果没有,请更换.+.*

该行的其余部分来自已接受的答案。

编辑:如果您想要帕累托图格式的排序良好的直方图,只需sort在末尾添加另一个即可:

find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$/\1/p' | sort | uniq -c | sort -bn

来自构建的Linux源代码树的样本输出:

    1 .1992-1997
    1 .1994-2004
    1 .1995-2002
    1 .1996-2002
    1 .ac
    1 .act2000
    1 .AddingFirmware
    1 .AdvancedTopics
    [...]
 1445 .S
 2826 .o
 2919 .cmd
 3531 .txt
19290 .h
23480 .c

1

我已经将bash脚本放到~/bin名为exhist以下内容的文件夹中:

#!/bin/bash

for d in */ ; do
        echo $d
        find $d -type f | sed -r 's/.*\/([^\/]+)/\1/' | sed 's/^[^\.]*$//' | sed -r 's/.*(\.[^\.]+)$/\1/' | sort | uniq -c | sort -nr
#       files only      | keep filename only          | no ext -> '' ext   | keep part after . (i.e. ext) | count          | sort by count desc
done

无论我在哪个目录中,我都只需键入“ exh”,使用制表符自动完成该操作,然后会看到类似以下内容的内容:

$ exhist
src/
      7 .java
      1 .txt
target/
     42 .html
     10 .class
      4 .jar
      3 .lst
      2 
      1 .xml
      1 .txt
      1 .properties
      1 .js
      1 .css

PS在问号后修剪部分应该很容易与另一个sed命令一起执行(可能在最后一个命令之后执行)(我没有尝试过): sed 's/\?.*//'

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.