如何在 Linux 上删除稀疏文件中的所有漏洞?在 Windows 上,我认为程序是
fsutil sparse setflag <file> 0
Linux 的对应版本是什么?
(我知道cp <file> <file>.cp; rm <file>; mv <file>.cp <file>;
如果可用磁盘空间允许的话可以完成这项工作,但我猜 Linux 有一种现成的方法可以完成它?像 Windows 一样?)
答案1
fallocate -l <length> <file>
可能会实现这一点;虽然它没有告诉文件系统明确地用零填充空洞,但它确实分配空间对他们来说。比较:
[make a sparse file]
$ echo yay | dd bs=1 seek=1G of=test.file
[list extents]
$ filefrag -v test.file
ext: logical_offset: physical_offset: length: expected: flags:
0: 262144.. 262144: 902523324.. 902523324: 1: 262144: last,eof
[allocate space]
$ fallocate -l $(stat -c %s test.file) test.file
[list extents again]
$ filefrag -v test.file
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 196607: 2219092376..2219288983: 196608: unwritten
1: 196608.. 262143: 2219301264..2219366799: 65536: 2219288984: unwritten
2: 262144.. 262144: 902523324.. 902523324: 1: 2219366800: last,eof
使用filefrag -v <file>
或xfs_io -r -c "fiemap -v" <file>
列出文件的范围。在此示例中,fallocate 之后不再有漏洞;它们现在被“未写入”的范围覆盖,文件系统将继续在读取时立即返回零,但现在做分配有特定的物理块。
从技术上讲,可以向 fallocate 添加一个选项,该选项使用 FIEMAP 列出漏洞和/或“未写入”的范围并用零填充它们,但不幸的是,它目前还没有这个选项,需要手动指定零填充偏移量/长度。
如果文件恰好在和之间被截断
stat -c %s
,fallocate
则后一个操作将使其再次增长到之前的大小。如果您希望文件再次增大,那么您可以避免使用这种方法
-n/--keep-size
(这种方法只预分配空间,但不会使文件增大),尽管我对 Linux 中分配 EOF 以外空间的确切语义不太清楚。(我想这类似于 Windows 的“fsutil file setEOF/setValidData”。)另一方面,如果文件成长在两次操作之间,它不会被截断;新添加的数据(或漏洞)将不会受到 fallocate 的影响。(也就是说,您不会丢失任何数据;最坏的情况是您只需要再次执行此操作即可摆脱新添加的漏洞。)
请注意
cp
– 在最近的 GNU Coreutils 版本中,它将自动尝试使用 SEEK_HOLE 来保持稀疏性。您可能需要使用 来cp --sparse=never
防止这种情况。此外,从 Coreutils 9.x 开始,如果文件系统支持
cp foo bar
,甚至cat foo > bar
会自动使用 FICLONE 或 copy_file_range() 操作来克隆文件而无需实际复制其数据,例如在 XFS 或 Btrfs 或 ZFS 上(类似于 ReFS 中的“块克隆”功能)。如果发生这种情况,“副本”将准确保留文件原始的稀疏性,您将
shared
在 filefrag 的输出中看到每个范围的标志。您可以使用cp --reflink=never
它来防止这种情况。(fallocate 系统调用有一个标志来取消共享范围,但它尚未通过
fallocate
命令行工具公开,尽管您可以通过xfs_io
具有“funshare”子命令来执行此操作。)