du 是什么
du 自底向上遍历目录树,把每个文件实际占用的磁盘块累加到父目录后输出。关键字是磁盘块而不是文件长度:稀疏文件只算实际分配的块,每个小文件至少占一个块,硬链接默认只统计一次。这三条决定了 du 的三个典型现象——小文件海量时 du 的结果明显大于 ls -l 的合计、稀疏文件上 du 远小于文件长度、以及 du 与 df 对不上时往往不是命令出错,而是被删除但仍被持有的句柄或文件系统的保留块在作怪。
基本信息
| 适用平台 | Linux 全发行版与 macOS(GNU coreutils / BSD du,--max-depth、--exclude 等为 GNU 写法) |
|---|---|
| 命令语法 | du [选项] [路径...];不写路径默认统计当前目录 |
| 常用选项 | -s 只输出总计、-h 人类可读、-a 连文件一起列出、--max-depth=N 限制层级、--exclude 排除、-x 不跨文件系统、-c 末尾加总计、--apparent-size 按文件长度而非块数统计、-l 硬链接重复计数 |
| 权限要求 | 读取目录需要 r 与 x 权限,缺权限的子树会被静默跳过,结果偏小 |
| 单位说明 | 默认以 1KiB 块为单位输出数字,-h 转为 KiB/MiB/GiB 可读格式 |
典型使用场景
- 逐层定位占用:--max-depth=1 先找出大目录,再对该目录继续下钻,比全盘扫描高效得多
- 单目录体量确认:du -sh /var/log 一条命令拿到总量,用于容量规划与告警阈值
- 排除干扰项:--exclude 跳过缓存、依赖目录、备份仓库,让结果聚焦真实业务数据
- 与 df 交叉验证:du 合计远小于 df 已用,优先怀疑已删除但仍被持有的文件或容器分层存储
- 归档与备份校验:打包前后各统计一次,确认体量合理再删除源数据
- 统计同类文件合计:du -ch 配合通配符拿到一批文件的总占用
常用示例
常用示例
du -sh /var/log # 单目录总量
du -h --max-depth=1 /var | sort -rh | head -n 10 # 逐层定位,按大小倒序
du -ah --exclude='*.log' --exclude=node_modules /data | sort -rh | head
du -ch /var/log/*.gz # 一批文件合计
du -shx /home # -x 不跨文件系统,避免把挂载盘算进来
du -sh --apparent-size /srv/tiny-files # 按文件长度统计,与 ls 口径对齐
du -sh /data/* 2>/dev/null | sort -rh | head -n 10选项对照
| 选项 | 作用 | 注意 |
|---|---|---|
| -s | 只输出每个参数的总计 | 最常用,配合 -h 即 du -sh |
| --max-depth=N | 限制输出层级,N 为最大深度 | 定位大目录的标准手法,先浅后深 |
| -x | 不跨越文件系统边界 | 排查根分区时必加,否则会把挂载的数据盘算进去 |
| --exclude | 按模式排除路径 | 模式匹配的是路径,写法与 shell 通配符一致 |
| --apparent-size | 按文件长度统计而非占用块数 | 与 ls -l 口径一致,适合核对文件清单 |
| -l | 硬链接重复计数 | 默认去重;报表要求与 df 对齐时再考虑使用 |
du 慢是因为它必须真的遍历整棵目录树,几十万 inode 的目录要读很久,且目录内容在统计过程中变化会让结果失去一致性。先用 --max-depth=1 定位到目标目录,再对目标目录下钻,比直接 du 全盘快得多。
du 与 df 的差异有三个常见来源:已删除但进程仍持有句柄的文件(du 看不到,df 算作已用)、ext4 等文件系统默认保留给 root 的约 5% 块(df 显示的可用空间小于总量减已用)、以及容器 overlay 与快照文件系统上被共享或引用的层。定位方向不同,先判断属于哪一类。
以普通用户对其他用户的目录执行 du,会因权限不足静默跳过大量内容,得到偏小的结果却被用作删除决策依据。涉及系统目录时统一加 sudo,并在结果里留意是否出现 Permission denied。