Linux怎么查看文件的逻辑大小与物理大小 Linux下du与ls差异详解

在Linux系统里,ls -l和du -h显示的文件大小经常“对不上号”,这可不是什么bug,而是文件系统底层设计的必然结果。简单来说,ls 显示的是文件的逻辑大小(st_size),而 du 统计的是物理磁盘占用(实际分配的块)。理解这背后的原因,是精准管理磁盘空间和排查问题的关键一步。
为什么 ls -l 和 du -h 显示的大小经常对不上
根本原因在于,这两个命令读取的数据来源完全不同。ls -l直接从文件的inode里读取st_size字段,这个值就是你“写进去多少字节”,是文件内容的逻辑长度。而du则要实在得多,它会去遍历文件实际占用的数据块,并且会聪明地跳过那些“空洞”,只计算真正分配了磁盘空间的部分。
这就导致了几个典型的场景:
- 稀疏文件:比如用
dd if=/dev/zero of=img bs=1M seek=1024 count=0命令创建一个镜像文件。ls -lh可能会告诉你它有1.0G,但du -h一看,实际磁盘占用可能只有200K。 - 小文件:一个只有1字节的文件,
ls -l诚实地显示为1。但du -h会显示4.0K,因为文件系统分配磁盘空间是以块为单位的(比如一个4KB的块)。 - 目录本身:
ls -ld显示的是目录项元数据的大小(通常是4.0K),而du -sh显示的是该目录下所有文件和子目录的总物理占用。 - 硬链接:对于指向同一个inode的多个硬链接,
ls会为每个链接名都显示完整的逻辑大小。而du默认会去重统计(同一个inode只算一次),除非你加上-l选项让它“老实”地逐个计算。
du 的 --apparent-size 是什么作用
那么,有没有办法让du也按逻辑大小来算呢?当然有,这就是--apparent-size选项的用武之地。加上它,du就会改用st_size(也就是ls用的那个值)来做计算,结果自然就和ls保持一致了。
这个功能特别适合那些需要“按内容长度汇总”的场景,比如估算备份数据的总量(关心的是数据本身有多大,而不是它在磁盘上占了多少“坑”)。
- 对比示例:
对一个大型稀疏文件执行:
du -h large_sparse_file→ 输出 12M(物理占用)
du -h --apparent-size large_sparse_file→ 输出 2.1G(逻辑大小,接近ls -lh的结果) - 需要注意:
--apparent-size只改变计算大小的依据,不影响硬链接的去重逻辑。如果你希望把每个硬链接都单独计入总量,仍然需要配合-l选项使用。 - 在编写脚本进行批量处理时,如果目标是统计“总写入字节数”,就应该优先使用这个选项,避免被文件空洞误导。
stat 命令怎么看逻辑大小和块数
如果想一次性、最直接地看清逻辑大小和物理占用的全貌,stat命令是最佳选择。它能同时展示Size(逻辑大小)和Blocks(实际分配的512字节块数),顺带还能看到IO Block(文件系统的块大小)。
- 执行
stat example.txt,你会看到类似这样的关键信息:
Size: 1048576→ 逻辑大小是1MB。
Blocks: 2048→ 实际占用了2048个块,每个块512字节,合计也是1MB(这说明文件没有空洞)。
IO Block: 4096→ 文件系统以4KB为单位进行分配。 - 这里有个简单的判断技巧:如果
Blocks × 512 < Size,那就说明这个文件是稀疏文件,内部存在空洞。 - 对于需要脚本化提取的情况,可以使用
stat -c "%s %b %B" file。它会分别输出st_size(逻辑大小)、块数、以及块大小(单位字节),非常方便。
生产环境里最容易忽略的一点
最后,也是在实际运维中最容易踩坑的一点:选择错误的指标会导致误判。
如果你的监控脚本或者日志轮转逻辑,只依赖ls -l来判断文件是否“过大”,很可能会漏掉真实的磁盘压力,因为稀疏文件看起来大,实际占盘小。反过来,如果只看du的物理占用,又可能在估算备份或传输数据量时严重低估。
所以,真正的判断依据必须结合具体场景:
想知道磁盘是不是快满了? 用du看物理占用。
想检查某次写入是否超过了限制? 用stat或ls看的st_size(逻辑大小)。
心里没底的时候怎么办? 最稳妥的办法就是两个命令都查一下,对比着看。
ls显示文件逻辑大小(st_size),du统计物理磁盘占用(实际分配块),二者差异源于数据来源不同:ls读inode的st_size,du遍历已分配数据块并跳过空洞。
