stat 和 ls 显示错误的文件大小(TB 错误)

stat 和 ls 显示错误的文件大小(TB 错误)

好的,我有一堆 vCard 文件,大小大约为 200 到 300 字节。

在尝试归档它们时,我想知道为什么花了这么长时间,并发现有一个文件的大小不对。 ls 和 stat 都显示大小约为 8.1 TB。 这很神奇,因为我的 SSD 大小只有 250 GB 左右。

还有一些其他文件的大小不正确,但这个显然是最大的一个。我已经对它进行了 fsck,但 (ext4) 文件系统中似乎没有错误。我该如何消除这个错误的大小?

谢谢,沃勒

答案1

电子名片似乎是文本文件格式。这是件好事,因为文本文件不应该包含空值 - 如果操作系统误认为该文件是稀疏文件包含非常长的空序列。

您可以使用ls -lks bigfile它来查看占用空间是否与视在空间不同。

您可以使用dd它将数据块(例如,仅前 500 个字节)提取到新文件中。然后您可以使用它hexdump来查看该块中是否有可恢复的文本。

如果您发现文件中充满了长串的空值,您可以尝试使用脚本读取文件并只将非空数据写入新文件。这样,您也许能够花点功夫构建一个正常大小的有效 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。您的里程可能会有所不同。

答案2

在 Linux 上(自 3.1 版起),您可以使用lseek()and SEEK_DATA/orSEEK_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);

相关内容