你一定遇到过这种情况,在一个有几百万文件的目录中执行ls命令,ls就卡在那了,是吧?
但是,用ls -l -f命令可以立即显示出文件。
如果你想删除当前目录中的所有文件,使用如下命令:
ls -l -f | xargs rm
在清理大量不需要的文件后,会留下一个巨大稀疏的目录对象(directory object)。
假如一个目录下有300万个文件,除了这些文件占用空间外,目录对象本身也会占用超过100M的空间。
你也许想重建一个目录来回收那100M空间。但是,如果目录是/tmp,那就要小心了,只能在单用户模式下操作。
ls命令为什么会卡住?
默认情况下,ls命令会将输出排序。为了排序,ls命令先将所有文件的名称读入内存。当遇到一个非常大的目录时,它就在那里不断地读入文件名,并且内存占用越来越大,直到将所有文件一次性以字母数字顺序列出来。
而 ls -l -f 命令并不执行排序操作,只是读取目录然后立即显示文件。
下面举个例子,有个目录,包含300万个文件,文件名称形如test_file_a_1, test_file_a_2, ..., test_file_a_3000000. 用Perl脚本以文件名中的数字编号顺序来创建这些文件。
可以用 ls -l -f 命令立即列出头几个文件:
$ time ls -l -f | head
.
..
test_file_a_2531963
test_file_a_467778
test_file_a_2677947
test_file_a_329896
test_file_a_835701
test_file_a_1266060
test_file_a_261887
test_file_a_311007
real 0m0.006s
user 0m0.000s
sys 0m0.008s
现在,去掉上面命令中的-l和-f标志,ls命令花了大约10000倍长的时间:
$ time /bin/ls | head
test_file_a_1
test_file_a_10
test_file_a_100
test_file_a_1000
test_file_a_10000
test_file_a_100000
test_file_a_1000000
test_file_a_1000001
test_file_a_1000002
test_file_a_1000003
real 0m57.880s
user 0m55.644s
sys 0m2.121s
除了变得更慢外,后者还占用了大量内存。
当ls命令真正开始打印文件名的时候,它已经在内存中存储了300万个文件名,使用了大约507M内存。
相反,ls -l -f 命令内存占用从未超过4.5M,少了100倍。
当你的文件夹下面文件特别多,尤其是文件名也比较长的时候,它会消耗掉非常多的block。当你遍历文件夹的时候,如果Page Cache中没有命中你要访问的block,就会穿透到磁盘上进行实际的IO。在你的角度来看,就是你执行完ls后,卡住了。
当一个 目录下有无数小文件时,你发现你用 du -sh /path/to 会很久有不出结果,甚至会因为 SSH timeout 而被退出当前shell 。
那么 试试这个:
ls -l /path/to/ | grep -wv "total" | awk '{sum+=$5} END{print sum/(1024^3)}'
当 /path/to/ 目录下有上百万个小文件时,基本就没法使用 du -sh 了 ,但是你 ls -l 就没问题 。
image.png适用场景:
- 统计目录下为 小文件,且数量巨大
- 统计目录下都是文件,如果有子目录,那么只会统计该子目录本身大小,而不是子目录下文件大小
那么你肯定会问,我确实要保存许许多多的文件,我该怎么办?
其实也很简单,多创建一些文件夹就好了,一个目录下别存太多,就不会有这个问题了。
工程实践中,一般的做法就是通过一级甚至是二级hash把文件散列到多个目录中,把单目录文件数量控制在十万或万以下。
参考
我一定要让所有人都知道awk这个实用操作
https://www.cnblogs.com/jujujulie/p/15742730.html
使用 AWK 统计不同文件格式的文件大小总和
https://blog.51cto.com/liubin0505star/2584404
用wk数组做统计分析
https://blog.51cto.com/lidao/1912219
Linux 统计文件的行数
http://www.manongjc.com/detail/51-hbieyrvumhknpnn.html
通过awk 统计字母频率
https://www.lxlinux.net/9822.html
awk算术运算一例:统计hdfs上某段时间内的文件大小
https://www.cnblogs.com/dyllove98/p/3239213.html
Linux查看文件大小的几种方法示例
https://www.cnblogs.com/renmengkai/p/9452883.html
Awk 学习笔记——基础篇
https://blog.csdn.net/longwen7/article/details/6336757
文件过多时ls命令为什么会卡住?
https://zhuanlan.zhihu.com/p/134207214
Linux 离奇磁盘爆满,如何解决?
https://zhuanlan.zhihu.com/p/111412537
Large Directory Causes ls to "Hang"
http://unixetc.co.uk/2012/05/20/large-directory-causes-ls-to-hang
文件处理命令:awk
https://www.programminghunter.com/article/89221444707
Linux中du命令和df命令有什么区别?
https://baijiahao.baidu.com/s?id=1709666864674037357&wfr=spider&for=pc
df和du显示的磁盘空间使用情况不一致的原因及处理
https://www.cnblogs.com/heyonggang/p/3644736.html
https://help.aliyun.com/document_detail/96228.html
Linux系统磁盘空间占满,df和du结果不一致
https://www.jianshu.com/p/3164d1a53e34
网友评论