stat und ls zeigen falsche Dateigröße (Terabytes falsch)

3714
WolleTD

Ok, ich habe eine Menge vCard-Dateien, alle etwa 200 bis 300 Bytes groß.

Beim Versuch, sie zu archivieren, habe ich mich gefragt, warum das so lange dauert, und ich habe festgestellt, dass es eine Datei mit einer falschen Größe gibt. Sowohl ls als auch stat zeigen eine Größe von etwa 8,1 Terabyte. Das ist erstaunlich, weil meine SSD nur etwa 250 Gigabyte groß ist.

Es gibt auch einige andere Dateien mit falschen Größen, aber dies ist eindeutig die größte. Ich gab es bereits ein Fsck, aber es scheint keine Fehler im (ext4) Dateisystem zu geben. Wie kann ich diese falsche Größe beseitigen?

Danke, Wolle

5
Nur eine Vermutung, aber vielleicht handelt es sich um (ungültige) spärliche Dateien. Das würde eine enorme Größe erklären. gronostaj vor 11 Jahren 2
Wie kann ich diese loswerden? Und wie kann eine spärliche Datei größer sein als meine Festplatte? WolleTD vor 11 Jahren 0
Stellen Sie sich eine Mappe vor, die 100 Seiten aufnehmen kann. Wenn Sie diese Mappe als reguläre Datei verwenden, können Sie 100 Seiten einfügen. Sie könnten alle 100 lesen. Sie könnten alle 100 schreiben. Stellen Sie sich nun ein spärliches Heft vor. Sie fügen die erste Seite ein, die Sie schreiben "Seite 1: Inhalt A". Sie fügen dann eine zweite Seite ein, die Sie schreiben "Seite 9999: Inhalt b:". Immer wenn Sie versuchen, eine Seite zu lesen, schauen Sie, ob sie existiert. Wenn dies nicht der Fall ist, lautet Ihre Antwort * Dies ist eine leere Seite *. Ist dies der Fall, geben Sie den Inhalt der Seite zurück. Wenn Sie auf eine Seite schreiben, die noch nicht in der Mappe vorhanden ist, fügen Sie ein neues Blatt hinzu. Hennes vor 11 Jahren 1
So ist es möglich, eine Mappe mit Seitennummer (lesen: Eine Datei mit einer Größe) größer als die zu haben, die in die Mappe passt, wenn alle Seiten vorhanden sind. Hennes vor 11 Jahren 0
Also und wie kann ich das beheben? Ich kann die Datei nicht einmal öffnen ... WolleTD vor 11 Jahren 1
@WolleTD Es ist wahrscheinlich beschädigt. Haben Sie versucht, es zu löschen? Paul vor 11 Jahren 0
Überprüfen, ob die Datei spärlich ist: `ls -lsh file` druckt die besetzte Größe in der neuen ersten Spalte. Wenn die belegte Größe kleiner als die scheinbare Größe ist, ist die Datei spärlich. pabouk vor 11 Jahren 1
@Paul dann ist es weg. Ich will nicht, dass es weg ist, ich brauche es. Ich kann weder den Inhalt lesen noch ihn kopieren, ohne dieselbe falsche Größe zu haben ... WolleTD vor 11 Jahren 0

2 Antworten auf die Frage

1
RedGrittyBrick

vCard scheint ein Textdateiformat zu sein. Dies ist eine gute Sache, da Textdateien keine Nullen enthalten sollten. Dies ist hilfreich, wenn das Betriebssystem fälschlicherweise der Meinung ist, dass die Datei eine spärliche Datei ist, die sehr lange Folgen von Nullen enthält.

Sie können verwenden, um ls -lks bigfilezu sehen, ob der belegte Raum vom scheinbaren Raum abweicht.

Sie können ddDatenblöcke (z. B. nur die ersten 500 Byte) in eine neue Datei extrahieren. Sie können dann verwenden, um hexdumpzu sehen, ob sich in diesem Block ein wiederherstellbarer Text befindet.

Wenn Sie feststellen, dass die Datei mit langen Folgen von Nullen gefüllt ist, können Sie versuchen, die Datei mit einem Skript zu lesen und nur die Nicht-Null-Daten in eine neue Datei zu schreiben. Auf diese Weise können Sie mit einiger Anstrengung eine gültige vCard-Datei der üblichen Größe erstellen.

Verwenden Sie alternativ strings bigfile, um Text aus der großen Datei zu extrahieren

Viele dieser Vorgänge werden für eine ig-Datei sehr lange dauern. Vielleicht möchten Sie etwas kleineres üben ...


Hier ist eine vCard-Datei

$ 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 

Lassen Sie uns eine korrupte spärliche Version machen

$ 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 

Beachten Sie, dass die Größe der letzten Datei auf der Festplatte 4 Blöcke beträgt, aber 5121 Datenblöcke enthält.

Mal sehen was da drin ist

$ 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 

Beachten Sie die *Linie zwischen den Offsets 290 und 0500280 - dort leben alle imaginären Nullen.

$ 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 

Wir haben unsere normale vCard aus der riesigen Datei wiederhergestellt. Ihr Kilometerstand kann variieren.

0
Eric Westbrook

Unter Linux (seit 3.1) können Sie lseek()die SEEK_DATAund / oder SEEK_HOLEPositionen von Daten und Löchern in einer Datei mit geringer Dichte identifizieren. Durch Wiederholen des Aufrufs mit zunehmendem Versatz können Sie die als Daten identifizierten Bytes lesen und in eine andere Datei schreiben, während Sie gehen. Vielleicht so etwas (Fehlerprüfung und andere Langeweile zur Vereinfachung weggelassen):

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);