重写目录树中所有文件的命令行工具

重写目录树中所有文件的命令行工具

是否有命令行工具可用于就地或通过创建新的索引节点重写目录树中的所有常规文件?

就地重写文件,我的意思是打开文件进行读写,读取合理大小的块并将这些块写入同一位置,对整个文件执行此操作。基本上这个命令行的作用是:

find dir -type f -print0 | xargs -0 -n1 bash -c 'dd if="$1" of="$1" conv=notrunc bs=64M' -

相反,如果创建了新的索引节点,则应尽可能替换文件属性,例如此命令的作用:

find dir -type f -print0 | xargs -0 -n1 bash -c 'echo "$1"; cp -a "$1" "$1~" && mv "$1~" "$1"' -


背景:

我正在尝试获得一些经验并寻找在适当的情况下使用 ZFS 重复数据删除的良好实践。 ZFS 重复数据删除使用滴滴涕(重复数据删除表)并对大小由文件的给定的块进行操作记录大小,这对重复数据删除的有效性和内存使用有影响。我正在探索迁移已写入数据以使用或停止使用 DDT 或更改文件记录大小的可能性。 ZFS 不会自动更改已写入数据的这些参数,因此需要重写数据。

要更改是否使用 DDT,只需在适当位置重写数据即可(无需创建新文件)。但是文件的记录大小是在创建时确定的,因此需要创建新文件来更改它。

答案1

我刚刚创建了可以做到这一点的工具:

https://github.com/pjd/filerewrite

或者,使用 ZFS,您还可以在目标文件系统启用重复数据删除的情况下使用 zfs send/recv。之后,您将需要重命名文件系统并确保所有其他文件系统属性都已移动。

答案2

(这个问题在我写这篇文章时已经有一年了,但它出现在我的评论队列中,所以我会回答它,以防其他人搜索类似的需求。)

这种工具不太可能存在在不同的文件系统类型之间是可靠的,尤其是在 *nix 系统中,该系统可能在系统根树的各个点安装了多个文件系统类型。这样做的原因是某些文件系统可能会在“幕后”执行额外的工作,并且不能保证重写会在同一个地方发生(实际上,您想要做的就是让 ZFS 准确地执行此操作)通过重写文件数据来消除重复!)除非文件系统本身已经支持这样的功能。

您可以编写一个快速程序以读+写模式打开文件,然后读取一个块,返回到块的开头,然后再次写入。我不知道这是否适用于 ZFS 重复数据删除,或者您可能会遇到哪些其他类型的问题。例如,加密的文件系统可能需要重新加密文件,和/或什至移动它在物理存储设备上物理存储的位置。这就是为什么您需要根据您的特定需求自己编写这样的工具的部分原因。

另一种方法是对文件树进行备份,然后在原始文件上恢复备份。然而,如上所述,这需要您有某种备份存储(尽管它可以是同一物理磁盘上其他位置的简单 tar 文件等),并适当选择备份和恢复选项。

作为最后的手段,您也许可以在其他地方重命名目录树,然后通过一次复制一个文件来重新创建它(在验证新文件已安全复制后删除旧文件,以释放空间)。您仍然需要足够的额外存储空间来制作最大单个文件的副本。在大多数情况下,这是不容易避免的,特别是如果文件系统驱动程序尝试足够高效以认识到数据实际上并未更改(例如,保留块哈希/校验和)并简单地丢弃不必要的写入。对于计算机来说,内存到/从内存的操作比内存到/从设备的操作要快得多。

相关内容