从命令提示符生成文件大小的分布

not*_*ter 27 linux unix bash command-line

我有一个包含几百万个文件的文件系统,我想在特定目录中递归地查看文件大小的分布。我觉得这完全可以用一些 bash/awk fu,但可以用手。基本上我想要如下内容:

1KB: 4123
2KB: 1920
4KB: 112
...
4MB: 238
8MB: 328
16MB: 29138
Count: 320403345
Run Code Online (Sandbox Code Playgroud)

考虑到循环和一些条件 log2 文件大小 foo,我觉得这应该不会太糟糕,但我似乎无法到达那里。

相关问题:如何找到大于/小于 x 字节的文件?.

gar*_*ohn 32

这似乎工作得很好:

find . -type f -print0 | xargs -0 ls -l | awk '{size[int(log($5)/log(2))]++}END{for (i in size) printf("%10d %3d\n", 2^i, size[i])}' | sort -n
Run Code Online (Sandbox Code Playgroud)

它的输出如下所示:

         0   1
         8   3
        16   2
        32   2
        64   6
       128   9
       256   9
       512   6
      1024   8
      2048   7
      4096  38
      8192  16
     16384  12
     32768   7
     65536   3
    131072   3
    262144   3
    524288   6
   2097152   2
   4194304   1
  33554432   1
 134217728   4
Run Code Online (Sandbox Code Playgroud) 其中左边的数字是从该值到两倍的范围的下限,右边的数字是该范围内的文件数。


小智 19

根据 garyjohn 的回答,这是一个单行,它还将输出格式化为人类可读的:

find . -type f -print0 | xargs -0 ls -l | awk '{ n=int(log($5)/log(2)); if (n<10) { n=10; } size[n]++ } END { for (i in size) printf("%d %d\n", 2^i, size[i]) }' | sort -n | awk 'function human(x) { x[1]/=1024; if (x[1]>=1024) { x[2]++; human(x) } } { a[1]=$1; a[2]=0; human(a); printf("%3d%s: %6d\n", a[1],substr("kMGTEPYZ",a[2]+1,1),$2) }'
Run Code Online (Sandbox Code Playgroud)

这是它的扩展版本:

find . -type f -print0                                                   \ 
 | xargs -0 ls -l                                                        \
 | awk '{ n=int(log($5)/log(2));                                         \
          if (n<10) n=10;                                                \
          size[n]++ }                                                    \
      END { for (i in size) printf("%d %d\n", 2^i, size[i]) }'           \
 | sort -n                                                               \ 
 | awk 'function human(x) { x[1]/=1024;                                  \
                            if (x[1]>=1024) { x[2]++;                    \
                                              human(x) } }               \
        { a[1]=$1;                                                       \ 
          a[2]=0;                                                        \
          human(a);                                                      \
          printf("%3d%s: %6d\n", a[1],substr("kMGTEPYZ",a[2]+1,1),$2) }' 
Run Code Online (Sandbox Code Playgroud)

在第一个中,awk我定义了最小文件大小以将所有小于 1kb 的文件收集到一个地方。在第二个中awk,函数human(x)被定义为创建一个人类可读的大小。这部分基于以下答案之一:https : //unix.stackexchange.com/questions/44040/a-standard-tool-to-convert-a-byte-count-into-human-kib-mib-etc -like-du-ls1

示例输出如下所示:

  1k:    335
  2k:     16
 32k:      5
128k:     22
  1M:     54
  2M:     11
  4M:     13
  8M:      3
Run Code Online (Sandbox Code Playgroud)