![¿Cómo ver el contenido de un archivo disperso?](https://rvso.com/image/154474/%C2%BFC%C3%B3mo%20ver%20el%20contenido%20de%20un%20archivo%20disperso%3F.png)
El tamaño del "archivo" muestra 15 TB cuando verifico el tamaño con ls -l
ls -l
total 16
-rw-r--r-- 1 root root 15393162788865 May 30 13:41 file
cuando verifico el tamaño del "archivo" con el comando du, muestra lo siguiente.
du -a file
12 file
Después de buscar en Google, llegué a la conclusión de que el archivo puede ser un archivo disperso. Los comandos como less, tail, cat, hexdump, etc. tardan una eternidad cuando los leo.
aquí está el resultado de filefrag.
filefrag -e file
Filesystem type is: ef53
File size of file is 15393162788865 (3758096385 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 0: 22261760.. 22261760: 1:
1: 3169274812..3169274812: 22268860.. 22268860: 1: 3191536572:
2: 3758096383..3758096383: 22271999.. 22271999: 1: 611090431: last
file: 3 extents found
Quiero saber si hay una manera de ver solo el contenido del archivo sin los agujeros/ceros desde la terminal de Linux.
Respuesta1
En los sistemas Linux más nuevos, existen SEEK_DATA
extensiones SEEK_HOLE
que lseek(2)
permiten que una aplicación omita "agujeros" al leer un archivo disperso.
En sistemas más antiguos, ioctl(FIBMAP)
se podría usar y los datos podrían leerse directamente desde el dispositivo subyacente ( aunque FIBMAP
necesita CAP_SYS_RAWIO
capacidades).
Desafortunadamente, no conozco ninguna utilidad coreutils/estándar que haga uso de ninguno de los dos.
Aquí hay una pequeña sparse_cat
demostración que los utiliza para volcar los datos de archivos dispersos muy grandes en poco tiempo.
Ejemplo:
$ cc -Wall -O2 sparse_cat.c -s -o sparse_cat
$ echo 1st | dd conv=notrunc status=none bs=1 seek=10M of=/tmp/sparse
$ echo 2nd | dd conv=notrunc status=none bs=1 seek=10G of=/tmp/sparse
$ echo 3rd | dd conv=notrunc status=none bs=1 seek=10T of=/tmp/sparse
$ ls -l /tmp/sparse
-rw-r--r-- 1 ahq ahq 10995116277764 May 30 16:29 /tmp/sparse
$ ./sparse_cat </tmp/sparse >/dev/tty
a00000 a01000
1st
280000000 280001000
2nd
a0000000000 a0000000004
3rd
Nota: para simplificar las cosas, omití cualquier código de apertura de archivos (siempre debe usarse como sparse_cat < input
, no sparse_cat input
) y cualquier solución alternativa para las malas interacciones entre sendfile(2)
y ttys abiertos con la O_APPEND
bandera (úsela >/dev/tty
explícitamente).
Observe también que los rangos de datos/agujeros tienen granularidad de bloque: la 1st
cadena del ejemplo anterior en realidad va seguida de block size - 4
bytes nulos.
sparse_cat.c
#define _GNU_SOURCE
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/sendfile.h>
int main(void){
off_t hole, data, pos, len; typedef unsigned long long ull;
for(hole = 0;; data = hole){
if((data = lseek(0, hole, SEEK_DATA)) == -1){
if(errno == ENXIO) return 0;
err(1, "lseek +data");
}
if((hole = lseek(0, data, SEEK_HOLE)) == -1)
err(1, "lseek +hole");
dprintf(2, "%16llx %16llx\n", (ull)data, (ull)hole);
for(pos = data; pos < hole;){
len = hole - pos; if(len > INT_MAX) len = INT_MAX;
if((len = sendfile(1, 0, &pos, len)) == 0) return 0;
if(len < 0) err(1, "sendfile");
}
}
}