如何删除 BTRFS 上 CoW 链接的文件的所有重复项

如何删除 BTRFS 上 CoW 链接的文件的所有重复项

写时复制 (CoW) 的优点在于,我们可以根据需要多次复制文件,而无需重复使用空间。

我在用于备份的驱动器上广泛使用了此功能(以及手动文件重复数据删除 - bees、bedup 和 rmlint)。我现在有许多包含大量数据的目录,它们彼此共享许多文件。

使用 baobab,我可以搜索此驱动器上的大文件,尝试删除一些旧的大文件,以便整理所有内容并为新备份腾出空间。问题是,在大多数情况下,删除一个大文件很可能不会释放任何空间,因为它的范围也被文件的另一个副本使用。

如果我找到某个文件并决定删除它,我会删除它的所有副本,因为我不再有兴趣保留它的任何副本。

更一般地说,如果我想从我的备份中删除一个完整的文件夹,我希望从它们可能包含的任何其他文件夹中删除其中包含的文件的所有副本。

如何删除 BTRFS 中的完整目录并删除其中包含的所有文件副本

我已经检查了“rm”的手册,但没有类似于这些情况下所需要的选项。

另一个问题问了一些类似的问题,但重点关注只读快照的问题,这对我来说通常不是一个问题。

答案1

我认为XY问题在你的问题中。你写的是:

如果我找到某个文件并决定删除它,我会删除它的所有副本,因为我不再有兴趣保留它的任何副本。

由于您不再想保留文件的任何副本,因此副本是重新链接、硬链接还是独立并不重要。您希望它们全部消失,对吗?

您专注于检测重新链接的文件,可能是因为您知道在您的案例中不会发生其他可能性;并且您可能希望针对 Btrfs 中重新链接的特定方法比通用方法更快。可能存在的问题:

  • 这种方法可能不会更快¹。比较检测硬链接,您需要检查所有文件并匹配 inode。要检测 reflink,您可能需要检查所有文件并匹配使用的块。不同的抽象层甚至更多的工作。

  • 共享块并非全有或全无。文件可能会被部分重新链接。各种情况都有可能发生。其中一些很常见(可能在制作快照或 CoW 副本后发生),有些则不太常见(例如,它们需要duperemove或您可能从未使用过的类似按需工具)。假设所讨论的文件由组成[block1][block2],以下是几个示例:

    • 另一个文件是[block1][block1][block3]。结论:仅仅找到一个共享块是不够的;您需要检查“原始”的所有块。
    • 有文件[block1][block3][block4][block2](但没有其他完全相同的文件[block1][block2])。结论:即使您知道“原始”的所有块都是共享的,您也不能确定“副本”是否存在;您需要检查它们是否都在某个“副本”内共享。
    • 另一个文件可能是[block2][block1]。结论:以上内容还不够;您需要检查“副本”中的块是否按正确的顺序排列。
      • 但如果[block1][block2]包含相同的数据(无论是偶然还是其他原因),那么[block1][block2][block2][block1]是相同的它们占据相同的空间。结论:“错误序列”和“正确序列”实际上可能是等价的。
    • 另一个文件可能是[block1][block2][block5]。结论:仅找到“原始”的所有块并按正确的顺序排列是不够的;您需要更仔细地检查所谓的“副本”。

出于这些原因,你应该考虑采用仅基于内容的方法,除非你想找到重新链接的副本仅有的(即你故意忽略(如果存在,则包含其他副本)。

似乎很容易(通过谷歌搜索)找到“查找重复项”的方法,但要找到“查找重复项”的方法却不那么容易。具体文件“。我的意思是常见的答案集中在查找一个或多个目录中的所有重复项集(例子)。重点是任何报告的集合都可能包含或不包含相关文件。我还没有测试所有可能的工具,其中一些工具可能提供一种严格与您想要的文件进行比较的方法,而不是“针对每个潜在对”。

如果工具不提供这样的方法,它至少可以提供根据文件大小包含/排除文件的方法。这可能会大大减少“所有潜在对”的集合,但仍可能出现一组不包含相关文件的重复项。

我认为我可以编写一个通用脚本,根据文件内容查找给定文件的重复项,并且速度相当快。由于问题集中在 Btrfs 中的 reflink,我认为这个答案不适合这样的脚本²。


¹) 我承认我没有测试过,因为我不知道这种方法。 如果我知道,我会把它放在答案中,因为这是你明确要求的。

²) 您(或任何人)可以提出一个单独的一般性问题,这是正确的地方。或者也许您设法找到一个已经存在的问题。在这个答案下给我留言,把我引到另一个地方。

相关内容