想象一下使用以下命令创建的文件:
truncate -s1T file
echo test >> file
truncate -s2T file
我现在有一个 2 tebibyte 文件(在磁盘上占用 4kiB),"test\n"
写入在中间。
我如何"test"
有效地恢复它,即无需读取整个文件。
tr -d '\0' < file
会给我结果,但这需要几个小时。
我想要的是只输出文件的非稀疏部分(因此上面仅"test\n"
或更可能是在存储该数据的磁盘上分配的 4kiB 块)。
有 API 可以找出文件的哪一部分已分配(FIBMAP、FIEMAP、SEEK_HOLE、SEEK_DATA...),但是哪些工具会公开这些内容呢?
一个可移植的解决方案(至少对于支持这些 API 的操作系统)将受到赞赏。
答案1
到目前为止我能想到的最好的办法是(ksh93,filefrag
从e2fsprogs
1.42.9 开始使用(一些旧版本有不同的 API),在 Linux 上基于范围的文件系统):
#! /bin/ksh93 -
export LC_ALL=C
for file do
filefrag -vb1 -- "$file" |
while IFS=": ." read -A a; do
[[ $a = +([0-9]) ]] && [[ ${a[@]} != *unwritten* ]] &&
command /opt/ast/bin/head -s "${a[1]}" -c "${a[7]}" -- "$file"
done
done
filefrag
使用支持它的文件系统的 FIEMAP ioctl 报告文件的范围。
该*unwritten*
部分涵盖了已fallocated
写入但尚未写入的文件(非稀疏,但仍然充满了我不感兴趣的零)。
bsdtar
或的最新版本star
可以使用其中一些 API 来生成一个tar
文件来识别稀疏部分。这将使更多便携的解决方案,但随后必须解析生成的 tar 文件才能获取非稀疏部分。