花拾录
← 返回知识库

统计目录大小算出来虚高:目录联接把另一个盘也算进去了

云计算 / 运维导入2026/09/220 阅读0 评论

磁盘快满了,你想知道空间到底是被哪个目录吃掉的。于是对某个看起来很大的目录做一次递归统计,算出好几个 GB,比你的预期大得多。你以为那里堆了一堆该清理的垃圾,结果点进去看,实际的物理文件并没有那么多——多出来的量,来自一块完全不同的盘。

现象

具体表现:

  • 对某个目录做递归求大小,得到的数字明显虚高;
  • 数字大得不像话,甚至可能超过该目录所在盘的剩余容量;
  • 逐层点进去核对,发现真实的文件量对不上算出来的总量;
  • 差额往往正好来自另一个盘的内容。

如果你算的是一个用户目录、媒体库目录、或者软件数据目录,这种现象尤其容易发生。

根因

罪魁祸首是目录联接(junction)或符号链接(symlink)。

目录联接是 Windows 上的"目录软链",指向另一个目录;Linux 上的符号链接同理。它本身几乎不占空间,只是一个"指路牌",告诉你"往这边走,真东西在那儿"。

问题出在递归枚举的行为上。当你对目录做"递归求所有文件大小"时,遍历器走到这个联结点,会顺着它走下去,进到它指向的那个真实目录,把里面的文件也一并算进来。如果这个联结指向的是另一块盘上的目录,结果就是:你统计 A 盘上的目录,却把 B 盘的内容也加了进去,数字自然虚高,甚至超过 A 盘的总容量。

这一层是很多人没意识到的:目录树在逻辑上可以跨越物理磁盘。看起来是"一个目录下面的东西",物理上可能分散在好几块盘上,靠软链串起来。递归统计如果不区分"物理归属",就会把跨越边界的都算进来。

除了虚高,反过来也有风险:有些工具为避免死循环,遇到符号链接会跳过不进入,于是又漏算了。所以同一个目录,不同工具算出的结果可能差很多,方向还不一样。

解决

要判断一块盘的真实占用,别用递归求和,直接看磁盘信息。

Windows:

# 看各卷的总容量、已用、可用
Get-Volume | Select-Object DriveLetter, FileSystemLabel, Size, SizeRemaining
# 或
Get-CimInstance Win32_LogicalDisk |
  Select-Object DeviceID, @{n='SizeGB';e={[math]::Round($_.Size/1GB,1)}},
                @{n='FreeGB';e={[math]::Round($_.FreeSpace/1GB,1)}}

Linux:

# 看各挂载点的总容量与已用
df -h

这些命令读的是文件系统自己的空间统计(已用多少、可用多少),不依赖遍历目录树,所以不会被软链带偏。要清理找占用,用这个方法先定位到"哪块盘满了",再在那块盘内部逐层找。

如果确实要递归统计一个目录,必须让工具不跨越文件系统边界:

Linux 下用 du 的 -x 选项(stay on one filesystem,只统计同一文件系统的内容):

# -x 不跨文件系统;-s 汇总;-h 人类可读
du -xsh /path/to/dir
# 按子目录排序找出大户
du -xh --max-depth=1 /path/to/dir | sort -h

Windows PowerShell 下,遍历时排除重解析点(reparse point,软链/联结在 Windows 上的底层实现):

Get-ChildItem -LiteralPath $path -Recurse -Force -ErrorAction SilentlyContinue |
  Where-Object { -not ($_.Attributes -band [IO.FileAttributes]::ReparsePoint) } |
  Measure-Object -Property Length -Sum |
  Select-Object Count, @{n='TotalGB';e={[math]::Round($_.Sum/1GB,2)}}

ReparsePoint 属性就是软链/联结的标记,把它排除掉,遍历就不会跑到别的盘去。

延伸与预防

这条坑的通用价值,是理解**"逻辑结构"和"物理布局"是两回事**。

目录树是逻辑视图,它可以通过软链、联结、挂载点、绑定挂载等方式跨越真实的物理边界。任何"沿着树往下走"的操作——统计大小、备份、搜索、删除、权限继承——都会遇到这个边界问题,而不同的工具对边界的处理方式还不统一:有的跟着走(虚高、甚至死循环),有的跳过去(漏算)。

所以做这类操作时,先明确一个问题:我要的是逻辑视图,还是物理视图?

  • 想知道磁盘到底还剩多少——用文件系统统计(df、卷信息),一切以物理为准;
  • 想备份一个目录树——要小心软链,决定是"复制链接本身"还是"复制链接指向的内容",tar、rsync 都有专门的选项来控制;
  • 想删除/扫描一个目录——更要注意别顺着软链跑到不该动的地方去。

预防很简单:跨盘统计用 -x,遍历时排除重解析点,把这当成默认习惯。养成先问"这个目录的边界在哪"的习惯,能避免一大批"数字对不上"和"误操作波及别的盘"的问题。

评论(0)

  • 还没有评论,来抢沙发~

相关文章