スパース ファイルの非スパース部分を表示するにはどうすればよいでしょうか?

スパース ファイルの非スパース部分を表示するにはどうすればよいでしょうか?

次のように作成されたファイルを想像してください:

truncate -s1T file
echo test >> file
truncate -s2T file

現在、2 テビバイトのファイル (ディスク上で 4 キロバイトを占有) があり、"test\n"その中央に書き込みがあります。

"test"ファイル全体を読み取らずに、効率的に回復するにはどうすればよいでしょうか。

tr -d '\0' < file

結果は得られますが、それには何時間もかかります。

私が欲しいのは、ファイルの非スパース部分のみを出力するものです (つまり、上記のみ、"test\n"またはおそらく、そのデータを格納するディスクに割り当てられた 4kiB ブロックのみ)。

ファイルのどの部分が割り当てられた(FIBMAP、FIEMAP、SEEK_HOLE、SEEK_DATA...) ですが、これらを公開するツールは何ですか?

移植可能なソリューション(少なくともこれらの API をサポートする OS に対して)が望まれます。

答え1

これまでのところ、私が思いついた最善の方法は、(ksh93、1.42.9filefrag以降を使用e2fsprogs(一部の古いバージョンでは 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

filefragFIEMAP ioctl を使用して、それをサポートするファイルシステムのファイルの範囲を報告します。

この*unwritten*部分は、書き込まれているがまだ書き込まれていないファイル (スパースではないが、ゼロがいっぱいで興味がない) をカバーしますfallocated

bsdtarまたはの最近のバージョンでは、starこれらのAPIの一部を使用して、tarスパースセクションを識別するファイルを生成できます。これにより、よりポータブル解決策ですが、生成された tar ファイルを解析して非スパース セクションを取得する必要があります。

関連情報