stat e ls mostrano dimensione file sbagliata (terabyte errata)

Ok, ho un sacco di file vCard, tutti di size da 200 a 300 byte.

Mentre cercavo di farli archiviare, mi sono chiesto perché questo richiede così tanto tempo e ha scoperto che c'è un file con una dimensione sbagliata. Sia ls che stat hanno mostrato una dimensione di circa 8.1 Terabyte. È incredibile perché il mio SSD è di soli 250 gigabyte.

Ci sono anche altri file con size sbagliate, ma questo è chiaramente il più grande. Ho già dato un fsck, ma sembra che non ci siano errori nel filesystem (ext4). Come posso liberarmi di questa dimensione sbagliata?

Grazie, Wolle

    vCard sembra essere un formato di file di text. Questa è una buona cosa in quanto i file di text non dovrebbero contenere nulli – questo aiuterà se il sistema operativo erroneamente pensa che il file è un file scarsissimo contenente sequenze molto lunghe di null.

    È ansible utilizzare ls -lks bigfile per vedere se lo spazio occupato differisce dallo spazio apparente.

    È ansible utilizzare dd per estrarre pezzi di dati (ad esempio i primi 500 byte) in un nuovo file. È quindi ansible utilizzare hexdump per vedere se c'è un text recuperabile in quel pezzo.

    Se il file è riempito di lunghe sequenze di null, è ansible provare a utilizzare uno script per leggere il file e scrivere solo i dati non null in un nuovo file. In questo modo potresti essere in grado di build un file vCard valido della dimensione abituale.

    in alternativa usa le strings bigfile per estrarre il text dal file enorme

    Molte di queste operazioni richiedono molto tempo su un file ig. Potresti voler praticare qualcosa di più piccolo …


    Ecco un file 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 

    facciamo una versione sparse corrotta

     $ 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 

    Si noti che la dimensione sul disco dell'ultimo file è di 4 blocchi ma contiene 5121 blocchi di dati.

    Vediamo cosa c'è dentro

     $ 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 

    Notate la linea * tra gli offset 290 e 0500280 – è where vivono tutti i null immaginari.

     $ 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 

    Abbiamo recuperato la nostra vCard di size normali dal file enorme. Il tuo chilometraggio può variare.

    Su linux (dal 3.1), è ansible utilizzare lseek() con SEEK_DATA e / o SEEK_HOLE per identificare posizioni di dati e fori in un file scarsissimo. Ripetendo la chiamata con un offset crescente, è ansible leggere i byte identificati come dati e scrivere in un altro file come si va. Forse qualcosa di simile (controllo degli errori e altro tedio omesso per semplicità):

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