web-dev-qa-db-ja.com

statとlsに間違ったファイルサイズが表示されます(テラバイトが間違っています)

わかりました。サイズが約200〜300バイトのvCardファイルがたくさんあります。

それらをアーカイブしようとしているときに、なぜそんなに時間がかかるのか疑問に思い、間違ったサイズのファイルが1つあることに気づきました。 lsとstatの両方が約8.1テラバイトのサイズを示しています。私のSSDのサイズは約250ギガバイトしかないので、これは驚くべきことです。

サイズが間違っているファイルも他にもいくつかありますが、これは明らかに最大のファイルです。私はすでにそれにfsckを与えましたが、(ext4)ファイルシステムにエラーはないようです。どうすればこの間違ったサイズを取り除くことができますか?

ありがとう、ウール

6
WolleTD

vCard はテキストファイル形式のようです。テキストファイルにnullが含まれていてはならないため、これは良いことです。これは、ファイルが非常に長いnullのシーケンスを含む スパースファイル であるとOSが誤って判断した場合に役立ちます。

ls -lks bigfileを使用して、占有スペースが見かけのスペースと異なるかどうかを確認できます。

ddを使用して、データのチャンク(最初の500バイトのみなど)を新しいファイルに抽出できます。次に、hexdumpを使用して、そのチャンクに回復可能なテキストがあるかどうかを確認できます。

ファイルがnullの長いシーケンスでいっぱいになっている場合は、スクリプトを使用してファイルを読み取り、null以外のデータのみを新しいファイルに書き込むことができます。このようにして、ある程度の努力で、通常のサイズの有効なvCardファイルを作成できる場合があります。

または、strings bigfileを使用して、巨大なファイルからテキストを抽出します

これらの操作の多くは、igファイルで長い時間がかかります。あなたはもっと小さな何かで練習したいかもしれません...


これがvCardファイルです

$ cat gump.vcard
BEGIN:VCARD
VERSION:2.1
N:Gump;Forrest
FN:Forrest Gump
...
EMAIL;PREF;INTERNET:[email protected]
REV:20080424T195243Z
END:VCARD

$ file gump.vcard
gump.vcard: vCard visiting card

破損したスパースバージョンを作成しましょう

$ dd of=sparse-file bs=1k seek=5120 count=0
0+0 records in
0+0 records out
0 bytes (0 B) copied, 0 s, Infinity B/s

$ cat gump.vcard sparse-file > sparse-gump.vcard

$ cp --sparse=always sparse-gump.vcard really-sparse-gump.vcard

$ ls -lks *sparse*
   0 -rw-r--r-- 1 rgb rgb 5120 Jul 11 18:09 sparse-file
5136 -rw-r--r-- 1 rgb rgb 5121 Jul 11 18:10 sparse-gump.vcard
   4 -rw-r--r-- 1 rgb rgb 5121 Jul 11 18:18 really-sparse-gump.vcard

最後のファイルのディスク上のサイズは4ブロックですが、5121ブロックのデータが含まれていることに注意してください。

そこに何があるか見てみましょう

$ hexdump really-sparse-gump.vcard | head -n 3
0000000 4542 4947 3a4e 4356 5241 0a44 4556 5352
0000010 4f49 3a4e 2e32 0a31 3a4e 7547 706d 463b
0000020 726f 6572 7473 460a 3a4e 6f46 7272 7365

$ hexdump really-sparse-gump.vcard | tail
0000230 4120 656d 6972 6163 450a 414d 4c49 503b
0000240 4552 3b46 4e49 4554 4e52 5445 663a 726f
0000250 6572 7473 7567 706d 6540 6178 706d 656c
0000260 632e 6d6f 520a 5645 323a 3030 3038 3234
0000270 5434 3931 3235 3334 0a5a 4e45 3a44 4356
0000280 5241 0a44 0000 0000 0000 0000 0000 0000
0000290 0000 0000 0000 0000 0000 0000 0000 0000
*
0500280 0000 0000
0500284

オフセット290と0500280の間の*行に注意してください。ここにすべての架空のヌルが存在します。

$ strings really-sparse-gump.vcard > new-gump.vcard

$ ls -lks new-gump.vcard
4 -rw-r--r-- 1 rgb rgb 1 Jul 11 18:30 new-gump.vcard

$ cat new-gump.vcard
BEGIN:VCARD
VERSION:2.1
N:Gump;Forrest
FN:Forrest Gump
...
EMAIL;PREF;INTERNET:[email protected]
REV:20080424T195243Z
END:VCARD

巨大なファイルから通常サイズのvCardを復元しました。あなたのマイレージは異なる場合があります。

1
RedGrittyBrick

Linux(3.1以降)では、lseek()SEEK_DATAおよび/またはSEEK_HOLEとともに使用して、スパースファイル内のデータとホールの位置を特定できます。オフセットを増やして呼び出しを繰り返すことにより、データとして識別されたバイトを読み取り、移動しながら別のファイルに書き出すことができます。おそらく次のようなものです(簡単にするためにエラーチェックやその他の面倒な作業は省略されています)。

int fd0 = open(file, O_RDONLY, S_IRWXU);
int fd1 = open(newfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
off_t eof = lseek(fd0, 0, SEEK_END);
off_t cur = 0;
char buf[8192];
while (cur < eof) {
  off_t d = lseek(fd0, cur, SEEK_DATA);
  off_t h = lseek(fd0, d, SEEK_HOLE);
  lseek(fd0, d, SEEK_SET);
  size_t dlen = min(h - d, 8192);
  ssize_t rlen = read(fd0, buf, dlen);
  ssize_t r = write(fd1, buf, rlen);
  cur = d + rlen;
}
close(fd0);
close(fd1);
0
Eric Westbrook