我有一个包含数百万个文件的文件系统,我希望在特定目录中递归查看文件大小的分布。我觉得用一些bash / awk fu完全可以做到,但是可以用一只手。基本上,我想要以下内容:
1KB: 4123
2KB: 1920
4KB: 112
...
4MB: 238
8MB: 328
16MB: 29138
Count: 320403345
我觉得给定一个循环和一些有条件的log2文件大小的foo应该不算太糟,但是我似乎不太能到达那里。
相关问题:如何查找比x字节大/小的文件?。
我有一个包含数百万个文件的文件系统,我希望在特定目录中递归查看文件大小的分布。我觉得用一些bash / awk fu完全可以做到,但是可以用一只手。基本上,我想要以下内容:
1KB: 4123
2KB: 1920
4KB: 112
...
4MB: 238
8MB: 328
16MB: 29138
Count: 320403345
我觉得给定一个循环和一些有条件的log2文件大小的foo应该不算太糟,但是我似乎不太能到达那里。
相关问题:如何查找比x字节大/小的文件?。
Answers:
这似乎工作得很好:
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
其输出如下所示:
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
其中,左边的数字是该值到该值的两倍范围的下限,右边的数字是该范围内的文件数。
ls
改为并不可行find
。我将其恢复原状。
xargs
的速度明显快于-exec
,因此我使用了该方法。
根据加里约翰(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) }'
这是它的扩展版本:
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) }'
首先,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
尝试这个:
find . -type f -exec ls -lh {} \; |
gawk '{match($5,/([0-9.]+)([A-Z]+)/,k); if(!k[2]){print "1K"} \
else{printf "%.0f%s\n",k[1],k[2]}}' |
sort | uniq -c | sort -hk 2
输出:
38 1K
14 2K
1 30K
2 62K
12 2M
2 3M
1 31M
1 46M
1 56M
1 75M
1 143M
1 191M
1 246M
1 7G
说明:
find . -type f -exec ls -lh {} \;
:足够简单,在当前目录中查找文件并ls -lh
在其上运行
match($5,/([0-9.]+)([A-Z]+)/,k);
:这将提取文件大小,并将每个匹配项保存到array中k
。
if(!k[2]){print "1K"}
:如果k[2]
未定义,则文件大小为<1K。由于我在想您不关心这么小的尺寸,因此该脚本将为1K
所有尺寸小于等于1K的文件打印。
else{printf "%.0f%s\n",k[1],k[2]}
:如果文件大于1K,则将文件大小四舍五入到最接近的整数,然后连同其修饰符(K,M或G)一起打印。
sort | uniq -c
:计算每行打印的次数(文件大小)。
sort -hk 2
:按照人类可读格式根据第二个字段排序。这样,7G
被排序8M
。