stat и ls показывают неверный размер файла (неправильный терабайт)

3643
WolleTD

Хорошо, у меня есть куча файлов vCard размером от 200 до 300 байт.

Пытаясь получить их в архиве, я удивился, почему это занимает так много времени, и обнаружил, что существует один файл с неправильным размером. И ls, и stat показывают размер около 8,1 терабайт. Это удивительно, потому что мой SSD имеет размер всего около 250 гигабайт.

Есть и другие файлы с неправильным размером, но это, безусловно, самый большой файл. Я уже дал fsck, но в файловой системе (ext4), похоже, нет ошибок. Как я могу избавиться от этого неправильного размера?

Спасибо Wolle

5
Просто предположение, но, возможно, это (недействительные) редкие файлы. Это объясняет огромные размеры. gronostaj 11 лет назад 2
как мне избавиться от них? И как разреженный файл может быть больше, чем мой жесткий диск? WolleTD 11 лет назад 0
Представьте себе переплет, способный вместить 100 страниц. Если вы используете этот переплет как обычный файл, вы можете вставить 100 страниц. Вы можете прочитать все 100. Вы можете написать все 100. Теперь представьте себе редкий переплет. Вы вставляете первую написанную вами страницу «страница 1: Содержание A». Затем вы вставляете вторую написанную вами страницу «страница 9999: содержание b:». Всякий раз, когда вы пытаетесь прочитать страницу, вы смотрите, если она существует. Если это не так, ваш ответ будет * это пустая страница *. Если он существует, вы возвращаете содержимое страницы. Всякий раз, когда вы пишете на страницу, которой еще нет в подшивке, вы добавляете новый лист бумаги. Hennes 11 лет назад 1
Таким образом, возможно иметь подшивку с номером страницы (читай: файл с размером) больше, чем тот, который поместится в подшивку, если присутствуют все страницы. Hennes 11 лет назад 0
И как мне это исправить? Я даже не могу открыть файл ... WolleTD 11 лет назад 1
@WolleTD Вероятно, поврежден. Вы пытались удалить его? Paul 11 лет назад 0
Проверка, является ли файл разреженным: `ls -lsh file` напечатает занятый размер в новом первом столбце. Если занятый размер меньше, чем видимый размер, файл является разреженным. pabouk 11 лет назад 1
@ Пол тогда ушел. Я не хочу, чтобы это ушло, мне это нужно. И я не могу ни прочитать его содержимое, ни скопировать его, не имея такой же, неправильный размер ... WolleTD 11 лет назад 0

2 ответа на вопрос

1
RedGrittyBrick

vCard appears to be a text file format. This is a good thing as text files should not contain nulls - this will help if the OS mistakenly thinks the file is a sparse file containing very long sequences of nulls.

You can use ls -lks bigfile to see if the occupied space differs from the apparent space.

You can use dd to extract chunks of data (e.g. the first 500 bytes only) into a new file. You can then used hexdump to see if there is recoverable text in that chunk.

If you find the file is filled with long sequences of nulls, you can try using a script to read the file and only write the non-null data to a new file. In this way you may be able, at some effort, to construct a valid vCard file of the usual size.

alternatively use strings bigfile to extract text from the huge file

Many of these operations will take a long time on a ig file. You may want to practise on something smaller ...


Here's a vCard file

$ cat gump.vcard BEGIN:VCARD VERSION:2.1 N:Gump;Forrest FN:Forrest Gump ... EMAIL;PREF;INTERNET:forrestgump@example.com REV:20080424T195243Z END:VCARD $ file gump.vcard gump.vcard: vCard visiting card 

let's make a corrupt sparse version

$ 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 

Note that the size on disk of the last file is 4 blocks but it contains 5121 blocks of data.

Lets see what is in there

$ 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 

Note the * line between offsets 290 and 0500280 - that's where all the imaginary nulls live.

$ 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:forrestgump@example.com REV:20080424T195243Z END:VCARD 

We have recovered our normal sized vCard from the huge file. Your Mileage May Vary.

0
Eric Westbrook

В Linux (начиная lseek()с версии 3.1) вы можете использовать с 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); 

Похожие вопросы