du 命令详解与参数实测(Ubuntu 22.04)
du 命令逐参数实测详解:默认递归 KB 统计、-h 人类可读、-s 汇总、-a 全文件、-b 真实字节、--max-depth 分层、--exclude 排除、-c 总计,并实测 du 与 df 统计口径差异及 deleted-but-open 场景,全部回显在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。
du 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 GNU du 的每一个参数——默认递归统计(KB 单位)、
-h人类可读、-s汇总、-a列出所有文件、-b真实字节、--max-depth分层统计、--exclude模式排除、-c总计,并实测 du 与 df 的统计口径差异,全部命令与回显已在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- du 版本:GNU coreutils 8.32(
du --version实测) - du 属于 coreutils 基础工具集,Ubuntu 22.04 默认预装,无需额外安装
- 演示目录:
/root/demo/du/ - 测试数据:
logs/(app.log 3MB、error.log 2MB)、data/raw/(users.csv 5MB、orders.csv 4MB)、data/index.bin2MB、docs/notes.txt5 字节、README.md7 字节,总计约 14MB
二、命令概览
2.1 语法与测试数据准备
du(disk usage)的基本语法是 du [OPTION]... [FILE]...:对每个 FILE 递归统计其占用的磁盘块数并输出,缺省时统计当前目录。注意 du 统计的是「磁盘占用」而非「文件内容大小」——文件按块对齐分配,1 字节的文件也要占一个 4KiB 数据块,这是后面多个实测结论的根源。
💡 技术拓展:"看磁盘用了多少"有一族工具,统计口径各不相同,横向对比——
工具 原理/职责 适用场景 du 沿目录树逐文件累计磁盘占用 定位"哪个目录占的空间大" df 按文件系统整体统计已用/可用块 看"整个分区还剩多少空间" stat -c %s 单文件的内容字节数(非块占用) 看单个文件的精确大小 ncdu du 结果的交互式浏览(需另装) 交互式逐层下钻清理空间 本文主角是 du:口径是"磁盘占用"(块对齐后),与 df 的"文件系统整体"互补——du 找元凶、df 看总量。
先准备一套多层目录、多种大小的演示数据,后续所有参数实测都基于这套数据:
rm -rf /root/demo/du && mkdir -p /root/demo/du/logs /root/demo/du/data/raw /root/demo/du/docs
dd if=/dev/zero of=/root/demo/du/logs/app.log bs=1M count=3 status=none
dd if=/dev/zero of=/root/demo/du/logs/error.log bs=1M count=2 status=none
dd if=/dev/zero of=/root/demo/du/data/raw/users.csv bs=1M count=5 status=none
dd if=/dev/zero of=/root/demo/du/data/raw/orders.csv bs=1M count=4 status=none
dd if=/dev/zero of=/root/demo/du/data/index.bin bs=1M count=2 status=none
printf 'readme\n' > /root/demo/du/README.md
printf 'note\n' > /root/demo/du/docs/notes.txt
验证数据就绪:
$ ls -lhR /root/demo/du
/root/demo/du:
total 16K
-rw-r--r-- 1 root root 7 Oct 15 06:28 README.md
drwxr-xr-x 3 root root 4.0K Oct 15 06:28 data
drwxr-xr-x 2 root root 4.0K Oct 15 06:28 docs
drwxr-xr-x 2 root root 4.0K Oct 15 06:28 logs
/root/demo/du/data:
total 2.1M
-rw-r--r-- 1 root root 2.0M Oct 15 06:28 index.bin
drwxr-xr-x 2 root root 4.0K Oct 15 06:28 raw
/root/demo/du/data/raw:
total 9.0M
-rw-r--r-- 1 root root 4.0M Oct 15 06:28 orders.csv
-rw-r--r-- 1 root root 5.0M Oct 15 06:28 users.csv
/root/demo/du/docs:
total 4.0K
-rw-r--r-- 1 root root 5 Oct 15 06:28 notes.txt
/root/demo/du/logs:
total 5.0M
-rw-r--r-- 1 root root 3.0M Oct 15 06:28 app.log
-rw-r--r-- 1 root root 2.0M Oct 15 06:28 error.log
2.2 --help 全量回显
du --help 输出全部参数清单(实测原样保留,可作为参数速查):
Usage: du [OPTION]... [FILE]...
or: du [OPTION]... --files0-from=F
Summarize disk usage of the set of FILEs, recursively for directories.
Mandatory arguments to long options are mandatory for short options too.
-0, --null end each output line with NUL, not newline
-a, --all write counts for all files, not just directories
--apparent-size print apparent sizes, rather than disk usage; although
the apparent size is usually smaller, it may be
larger due to holes in ('sparse') files, internal
fragmentation, indirect blocks, and the like
-B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,
'-BM' prints sizes in units of 1,048,576 bytes;
see SIZE format below
-b, --bytes equivalent to '--apparent-size --block-size=1'
-c, --total produce a grand total
-D, --dereference-args dereference only symlinks that are listed on the
command line
-d, --max-depth=N print the total for a directory (or file, with --all)
only if it is N or fewer levels below the command
line argument; --max-depth=0 is the same as
--summarize
--files0-from=F summarize disk usage of the
NUL-terminated file names specified in file F;
if F is -, then read names from standard input
-H equivalent to --dereference-args (-D)
-h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)
--inodes list inode usage information instead of block usage
-k like --block-size=1K
-L, --dereference dereference all symbolic links
-l, --count-links count sizes many times if hard linked
-m like --block-size=1M
-P, --no-dereference don't follow any symbolic links (this is the default)
-S, --separate-dirs for directories do not include size of subdirectories
--si like -h, but use powers of 1000 not 1024
-s, --summarize display only a total for each argument
-t, --threshold=SIZE exclude entries smaller than SIZE if positive,
or entries greater than SIZE if negative
--time show time of the last modification of any file in the
directory, or any of its subdirectories
--time=WORD show time as WORD instead of modification time:
atime, access, use, ctime or status
--time-style=STYLE show times using STYLE, which can be:
full-iso, long-iso, iso, or +FORMAT;
FORMAT is interpreted like in 'date'
-X, --exclude-from=FILE exclude files that match any pattern in FILE
--exclude=PATTERN exclude files that match PATTERN
-x, --one-file-system skip directories on different file systems
--help display this help and exit
--version output version information and exit
Display values are in units of the first available SIZE from --block-size,
and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environment variables.
Otherwise, units default to 1024 bytes (or 512 if POSIXLY_CORRECT is set).
The SIZE argument is an integer and optional unit (example: 10K is 10*1024).
Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers of 1000).
Binary prefixes can be used, too: KiB=K, MiB=M, and so on.
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/du>
or available locally via: info '(coreutils) du invocation'
💡 说明:du 的核心参数分三类——统计对象(
-a全部文件、-s只看汇总、-d/--max-depth限深)、单位(-h、-b、-k、-m、-B、--si)、过滤(--exclude、-X、-t、-x单文件系统)。帮助尾段说明了默认单位是 1024 字节(即 1K 一块),本文实测均基于该默认值。
2.3 版本确认
$ du --version | head -1
du (GNU coreutils) 8.32
三、参数逐项实测
3.1 默认用法:递归统计(KB 单位)
不带任何参数,du 对指定目录(缺省为当前目录)做递归统计,每个子目录输出一行:块数 + 目录名。默认单位是 1024 字节(1K):
$ cd /root/demo/du && du
9220 ./data/raw
11272 ./data
8 ./docs
5124 ./logs
16412 .
五个输出行的顺序是深度优先:先统计最深的 ./data/raw(9220K,即 users.csv 5MB + orders.csv 4MB 加目录块),再算出父目录 ./data(11272K,含 index.bin 2MB),./docs 只有 8K(一个 5 字节的文本文件加目录块),最后 . 汇总全部为 16412K。父目录的值包含其所有子目录的占用。
💡 提示:默认输出以 1024 字节为 1K(
du的 16412K 换算约 16MB)。想要 1000 进位可加--si(帮助原文:like -h, but use powers of 1000 not 1024)。
3.2 -h:人类可读单位
-h(--human-readable)把块数换算成 K/M/G 自动选单位:
$ du -h /root/demo/du
9.1M /root/demo/du/data/raw
12M /root/demo/du/data
8.0K /root/demo/du/docs
5.1M /root/demo/du/logs
17M /root/demo/du
与 3.1 逐行对应:9220K 显示为 9.1M(9220/1024≈9.0,加上目录块后四舍五入)、16412K 显示为 17M。日常排查建议直接 du -h,人眼读 K 数太费劲。
💡 提示:
-h以 1024 为底(M=1024K);--si以 1000 为底(M=1000K),两者显示值会略有差异,写文档/报表时注意统一口径。
3.3 -s:只看汇总(summarize)
-s(--summarize)对每个参数只输出一行总计,不再逐层展开:
$ du -sh /root/demo/du
17M /root/demo/du
$ du -s /root/demo/du/logs /root/demo/du/data /root/demo/du/docs
5124 /root/demo/du/logs
11272 /root/demo/du/data
8 /root/demo/du/docs
第一个示例是最常用的「看这个目录一共多大」;第二个示例对三个子目录各自给一行总计(不带 -h,单位仍是默认 K),适合横向对比几个同级目录的大小。
💡 提示:
-s等价于--max-depth=0(帮助原文:--max-depth=0 is the same as --summarize),见 3.7。
3.4 -a:列出所有文件(不只目录)
默认 du 只输出目录行;-a(--all)把每个文件也列出来:
$ du -a /root/demo/du/docs
4 /root/demo/du/docs/notes.txt
8 /root/demo/du/docs
$ du -ah /root/demo/du/docs
4.0K /root/demo/du/docs/notes.txt
8.0K /root/demo/du/docs
notes.txt 内容只有 5 字节,但块分配后占 4K(1024 块数)——目录总计 8K = 文件块 4K + 目录自身块 4K。-ah 组合即「所有条目 + 人类可读」。
💡 提示:
-a与-s是两种视角:-a逐条列、-s只给总。需要「按大小排序的文件清单」时用-a配合 sort(见四、实战示例)。
3.5 -b: apparent size,真实字节
-b(--bytes)等价于 --apparent-size --block-size=1(帮助原文),输出文件内容的真实字节数,不再按块对齐:
$ du -b /root/demo/du/docs/notes.txt /root/demo/du/README.md
5 /root/demo/du/docs/notes.txt
7 /root/demo/du/README.md
$ ls -l /root/demo/du/docs/notes.txt
-rw-r--r-- 1 root root 5 Oct 15 06:28 /root/demo/du/docs/notes.txt
-b 显示 5 字节,与 ls -l 的 5 完全一致;而不带 -b 的默认 du(见 3.4)显示 4(即 4K 块)。-b 回答「文件有多大」,默认模式回答「文件占多少磁盘」。
💡 提示:对稀疏文件(sparse file),apparent size 可能大于磁盘占用(帮助原文说明:may be larger due to holes in ('sparse') files),两个口径谁大谁小并不固定。
3.6 --max-depth=1:限制统计深度
--max-depth=N 只输出距命令行参数 N 层以内的目录总计,更深的子层折叠进父层:
$ du -h --max-depth=1 /root/demo/du
12M /root/demo/du/data
8.0K /root/demo/du/docs
5.1M /root/demo/du/logs
17M /root/demo/du
与 3.2 相比,data/raw 这一层不再单独出现,9.1M 被并入 data 的 12M;末尾仍保留参数本身的总计 17M。「每个一级子目录各占多少」这类排查问题,--max-depth=1 一条命令就能回答。
💡 提示:
--max-depth=0与-s等价;--max-depth=1保留一级子目录、2保留两级,依此类推。短选项-d N同义(帮助原文-d, --max-depth=N)。
3.7 --exclude:按模式排除
--exclude=PATTERN 不统计匹配 PATTERN 的条目。先用不带排除的输出做基线,再排除 *.log:
$ du -ah /root/demo/du/logs
2.0M /root/demo/du/logs/error.log
3.0M /root/demo/du/logs/app.log
5.1M /root/demo/du/logs
$ du -ah --exclude='*.log' /root/demo/du/logs
4.0K /root/demo/du/logs
两个 5MB 级的 .log 文件被整体排除后,logs 目录只剩目录自身的 4.0K 块。排除日志、缓存等可再生文件来评估「净数据量」时非常好用。
💡 提示:PATTERN 用 shell 通配风格(
*匹配任意串),匹配对象是路径的每一层文件名,因此--exclude='*.log'能命中任意目录下的日志。批量模式可写进文件用-X, --exclude-from=FILE,按大小过滤则用-t, --threshold=SIZE(均为帮助原文参数)。
3.8 -c:追加总计行
-c(--total)在原有输出的末尾追加一行 total:
$ du -ch /root/demo/du/logs/*
3.0M /root/demo/du/logs/app.log
2.0M /root/demo/du/logs/error.log
5.0M total
$ du -c /root/demo/du/logs/*
3072 /root/demo/du/logs/app.log
2048 /root/demo/du/logs/error.log
5120 total
第一个示例对通配符展开出的两个文件逐个统计并给出合计 5.0M;第二个示例不带 -h,可见合计 5120K = 3072K + 2048K。-c 的价值在于「既要明细也要总和」的场景。
💡 提示:
-c是在其他参数行为之上追加总计行,可与-h、-a、--max-depth等自由组合;只想要一行总数用-s即可,不必-c。
四、实战示例
4.1 分层定位大目录
磁盘告警时的标准动作:先用 --max-depth=1 看一级分布,再对最大的一层继续下钻:
$ du -h --max-depth=1 /root/demo/du
12M /root/demo/du/data
8.0K /root/demo/du/docs
5.1M /root/demo/du/logs
17M /root/demo/du
一眼看出 data 是大头(12M);继续用 -h 下钻确认细节构成:
$ du -h /root/demo/du
9.1M /root/demo/du/data/raw
12M /root/demo/du/data
8.0K /root/demo/du/docs
5.1M /root/demo/du/logs
17M /root/demo/du
定位到 data/raw 的 9.1M(两个 CSV 文件)。
4.2 多目录横向对比
把几个候选目录一起传给 du,用 -s 各出一行总计(不带 -h 时单位统一为 K,数值可直接比大小):
$ du -s /root/demo/du/logs /root/demo/du/data /root/demo/du/docs
5124 /root/demo/du/logs
11272 /root/demo/du/data
8 /root/demo/du/docs
4.3 清理前评估:排除可再生文件
清理动作执行前,先评估「排除日志后还剩多少净数据」:
$ du -ah --exclude='*.log' /root/demo/du/logs
4.0K /root/demo/du/logs
若要保留明细同时拿合计,用 -c:
$ du -ch /root/demo/du/logs/*
3.0M /root/demo/du/logs/app.log
2.0M /root/demo/du/logs/error.log
5.0M total
4.4 与 df 对照:口径差异速查
du -sh 只统计目录树(本例 17M),df -h 统计的是整个文件系统(同一台机器的根分区 786G、已用 441G):
$ du -sh /root/demo/du
17M /root/demo/du
$ df -h /root/demo/du
Filesystem Size Used Avail Use% Mounted on
overlay 786G 441G 310G 59% /
两者数字本来就不是一个口径,不能直接对账;真正的「对不上」问题(包括删了文件空间不释放)见五、注意事项 Q1。
五、注意事项与常见问题
Q1:du 和 df 看到的占用为什么对不上? 两者统计口径不同:du 沿目录树累加文件块,回答「这些文件占多少」;df 读文件系统的空闲块元数据,回答「整个分区还剩多少」。对不上有两类典型原因:一是 du 覆盖不到其他目录/其他文件系统(du 之外还有别的数据在占空间),二是已删除但仍被进程占用的文件——目录树里已经不存在,du 统计不到,df 却仍计入已用。下面实测第二种场景:先创建 40MB 文件并让一个进程持有它,再删除:
$ dd if=/dev/zero of=/root/demo/du/deleted-open.bin bs=1M count=40 status=none
$ rm /root/demo/du/deleted-open.bin
$ ls -l /root/demo/du
total 16
-rw-r--r-- 1 root root 7 Oct 15 06:28 README.md
drwxr-xr-x 3 root root 4096 Oct 15 06:28 data
drwxr-xr-x 2 root root 4096 Oct 15 06:28 docs
drwxr-xr-x 2 root root 4096 Oct 15 06:28 logs
$ du -sh /root/demo/du
17M /root/demo/du
$ df -h / | tail -1
overlay 786G 442G 310G 59% /
文件已从目录树消失(ls 与 du 都看不到),但根分区已用反而从 441G 涨到 442G——40MB 空间仍被占用。通过 /proc 能看到持有者(266 为当时持有该文件的进程 PID,fd 100 是它打开该文件的描述符):
$ ls -l /proc/266/fd/100
lr-x------ 1 root root 64 Oct 15 06:28 /proc/266/fd/100 -> /root/demo/du/deleted-open.bin (deleted)
(deleted) 标记即「已删除但仍打开」。等该进程退出、关闭描述符后,空间立即释放:
$ df -h / | tail -1
overlay 786G 441G 310G 59% /
排查此类问题时:df 显示占用高、du 逐层加总却小一截,就去查 lsof | grep deleted 或重启对应服务。
Q2:du 统计的文件大小和 ls 看到的不一样?
默认 du 按磁盘块统计,1 字节的文件也占 1 个 4K 数据块(见 3.4:5 字节的 notes.txt 统计为 4K);ls -l 与 du -b 显示的都是内容字节数(见 3.5:同为 5)。评估「传输/下载多大」用 -b 口径,评估「占多少盘」用默认口径。
Q3:--exclude 排除后,目录本身还剩 4.0K 是什么?
排除只作用于匹配的文件,目录自身的 inode 块(ext4 上一个目录至少占一块)不受影响(见 3.7 实测剩余 4.0K)。另外 PATTERN 匹配的是文件名而不是完整路径,--exclude='*.log' 会命中所有层级下的日志。
Q4:-s 和 --max-depth=0 是什么关系?
完全等价,帮助原文明确写着 --max-depth=0 is the same as --summarize。区别只在书写习惯:-s 短且常用,--max-depth 在需要 1、2 等非零深度时才登场(见 3.3、3.6)。
Q5:-h 显示的 M 是 1000K 还是 1024K?
1024K。-h 按二进制幂(1024)换算,--si 才按十进制幂(1000)换算(帮助原文:like -h, but use powers of 1000 not 1024)。与 ls -lh、free -h 保持同一口径即可。
Q6:硬链接、符号链接会影响 du 的结果吗?
默认情况下:du 不跟随符号链接(帮助原文 -P, --no-dereference don't follow any symbolic links (this is the default)),硬链接只在首次遇到时计一次、后续重复出现的硬链接不再重复计数;如需「每个硬链接都算一遍」用 -l, --count-links,如需把命令行里的符号链接当目录展开用 -L, --dereference。本套演示数据未包含链接,此处仅依据帮助原文说明语义。
六、参考链接
- GNU coreutils 官方手册(du 章节):https://www.gnu.org/software/coreutils/manual/html_node/du-invocation.html
- 在线文档:https://www.gnu.org/software/coreutils/du
- 本机帮助:
du --help、man du(Ubuntu 22.04 内置)