为什么在 Linux 中即使删除了目录的文件和子目录,目录大小仍然保持不变?

为什么在 Linux 中即使删除了目录的文件和子目录,目录大小仍然保持不变?

为什么在 Linux 中即使删除了目录的文件和子目录,目录大小仍然保持不变?

我创建了一个目录 vv1,并在其中创建了 500 个文件。ls -lrt显示大小 vv1 为 12288,如下所示:

total 12 

drwxr-xr-x 2 cms ccsrm 12288 Jan 28 12:15 vv1  

删除 500 个文件后,显示大小相同

total 12 

drwxr-xr-x 2 cms ccsrm 12288 Jan 28 12:17 vv1

为什么?

答案1

因为性能,也因为从总体上看,与其他事情相比,这是一个微不足道且毫无意义的问题。

在性能方面,让我们使用更简单的用例。当您创建目录并向其中添加文件时,您实际上是在创建一个文件,其中列出了其他文件、文件名、文件属性、创建日期等。每个新文件都会将另一个文件添加到该列表中。

现在想象一下,你想从数千个列表中删除一个文件。你有两个选择。

  1. 加载整个列表,删除不需要的条目,再写回整个列表,或者至少写回列表的其余部分。
  2. 更改已经存在的属性,即“该文件是否被删除”。

选项 1 涉及未知大小的读取,搜索整个内容以查找条目,将所有剩余数据向下移动该条目的大小,然后将整个列表重写回磁盘。这可能不会最终位于与原始位置相同的位置,并且可能需要更新其他文件系统结构以指向目录块。您可能不必写入整个目录,但您必须修改并重写您更改的条目之后的所有内容。这对较旧的条目来说会更糟,对较新的条目来说会更好,从而导致根据文件年龄删除文件的时间不一致。

选项 2 可以涉及更改目录“文件”中的一个字节。它可以(本质上)搜索目录,读取包含文件条目的扇区,更改一个字节(其他内容不变)并将该扇区写回原来的位置。对于要读取或写入的数据量没有任何不确定性,也没有其他要更新的数据位。

选项 2 更快、更高效,更重要的是,在目录规模更大的情况下,它的扩展性可能会更好。两种操作都具有相同的初始目录读取操作,即查找要删除的条目,但选项 2 不会因将条目写回而产生巨大损失,因此速度会更快。使用选项 1 删除大量文件可能会导致在规模极大的目录中写入大量数据,尤其是在删除“最旧”文件时。

因此大多数时候设计师会选择选项 2。

这样做的好处是,至少在数据块被重新使用或目录条目被重写之前,文件可以取消删除或恢复。

但是您可能会问,为什么没有运行并“清理”目录的计划任务。这是一个“我们真的需要吗?”的问题。最终,该条目可能会被重新用于新文件,这意味着可以进行类似于删除的就地更改,但在同一位置使用新文件。您应该何时运行清理?遍历整个系统目录结构在最好的情况下也很麻烦,并且在不合适的时刻这样做会使系统无法使用。您不能在启动时执行此操作,因为这会使系统启动时间过长,也不能将关机延迟几分钟。在系统运行时执行此操作同样没有帮助,因为它会减慢磁盘访问速度,因为其他任务会读写。

如果我们不断修剪列表,那么每次添加新项目时,我们都必须扩展列表(每次都会导致大小变化),这意味着其他文件系统数据需要更新。这更有可能导致性能不佳、写入次数超过必要次数,并且目录最终出现碎片的可能性也更大。

简单的答案是,不缩小目录是设计选择的混合。

  1. 不这样做可能意味着性能提升
  2. 对于给定的目录大小,速度保持一致
  3. 轻松重用条目,而无需修改其他文件系统结构
  4. 虽然不能保证,但有恢复文件的可能性
  5. 与目录中保存的文件相比,目录在磁盘上的实际大小非常小。
  6. 可以通过将文件移出该目录然后删除它来消除多余的文件夹大小,释放空间。

因此,有充分的理由不这样做,如果需要的话可以很容易地修复,而且很可能不是本来就不是什么大事。

这并不是说所有文件系统都以同样的方式执行此操作,或者这是“最佳”方式。这是对为何做出这些选择及其影响的解释。

答案2

这个问题已经回答过了这里 您在此处看到的大小并不告诉您目录内容占用了多少空间,而只是目录本身所需的元数据量,如果您添加或删除文件,元数据量也不会改变。

如果您想知道目录内存储了多少内容,您应该使用du而不是ls

相关内容