du -sh是唯一能准确反映文件夹真实磁盘占用的命令,因其遍历文件系统块并累加实际占用;ls -lh仅显示目录inode元数据(如4096字节),不递归统计内容,故无法代表目录真实空间消耗。

du -sh 是唯一能快速、准确反映文件夹真实磁盘占用的命令,其他方式(如 ls -lh、stat)只显示单个文件元数据或逻辑大小,对目录本身无意义。
为什么不能用 ls -lh 看文件夹大小
你知道吗?ls -lh 这个命令对目录显示的只是一个固定值(通常是4096字节),这其实是inode占用的空间,而并非目录内所有内容的总和。而且啊,它根本不会去递归统计子项。所以呢,当你执行 ls -lh /var/log 时,看到输出的“4.0K”,这和实际可能有几百MB的日志文件完全没有关系哦。
常见误操作:ls -lh */ 看子目录——这会漏掉隐藏目录(如 .git)、权限不足跳过的路径,且不包含目录自身结构开销(如 ext4 的目录索引块)。
ls类命令本质是列出条目,不是计算磁盘使用- 想看“这个文件夹占多少磁盘”,必须走文件系统块遍历,只有
du做这件事 - 图形界面文件管理器显示的“大小”底层调用的也是
du或类似逻辑,不是ls
du -sh 的正确用法和易错点
-s(summary)和 -h(human-readable)必须同时用;单独 du -s 输出的是 512 字节块数(比如 12345),人眼无法判断是 6MB 还是 6GB。
- 查当前目录总大小:
du -sh .或直接du -sh - 查指定路径:
du -sh /var/log,路径含空格时加引号:du -sh "/home/user/My Projects" - 权限不足会报
Permission denied,但结果仍可用;加2>/dev/null屏蔽干扰:du -sh /etc 2>/dev/null - 别写成
du -sh *——它只匹配非隐藏项,漏掉.config等关键目录;要全量统计,必须指定目录本身,不是通配符
大目录下快速定位“谁最占空间”
当 du -sh /var 显示 12G,但不知道哪块拖累时,用 --max-depth=1 一层展开,再配合 sort -hr 排序:
du -sh --max-depth=1 /var/* 2>/dev/null | sort -hr
关键细节:
--max-depth=1必须显式写,否则du会递归到底,耗时且输出爆炸sort -hr中-h支持 K/M/G 解析,-r倒序;没-h就按字符串排,“10M” 会排在 “2G” 前面/var/*不包含/var/.log这类隐藏项;更全写法是du -sh --max-depth=1 /var/.[^.]* /var/* 2>/dev/null | sort -hr- 遇到
/proc、/sys报错,2>/dev/null过滤即可,不影响主体排序
为什么 df 和 du 结果经常不一致
这不是命令错了,而是统计对象不同:df 看文件系统已分配的数据块,du 看路径下可见文件的块总和。
- 典型场景:进程正在写一个 5G 日志,你
rm -f /var/log/app.log,du立即变小,df仍显示 5G 被占——因为 inode 还被进程持有,块未释放 - 查谁卡着空间:
lsof +L1或lsof | grep deleted - 清理前务必确认:删
/var/spool/clientmqueue前先postsuper -d ALL,而不是rm -rf - 大量小文件时,
du可能慢;加--exclude跳过node_modules、.git:du -sh --exclude="node_modules" --exclude=".git" .
真正的难点并非在于如何敲击命令,而是当看到一个“20G”的目录时,需要瞬间做出判断:它是日志轮转后残留的?是journalctl未清理导致的?还是某个服务将临时文件写入了不该写入的地方——du会给你呈现数字,但这些数字背后所隐藏的故事,却需要依靠丰富的经验来进行补全。