¿Por qué ls -l genera un tamaño diferente de ls -s?

38

No puedo entender por qué obtengo los siguientes resultados:

ls -l me dice que el tamaño de un archivo dado (HISTORIA) es "581944":

$ ls -l HISTORY 
-rw-rw-r-- 1 waldyrious waldyrious 581944 Feb 22 10:59 HISTORY

ls -s dice que es "572":

$ ls -s HISTORY
572 HISTORY

Obviamente necesito hacer que los valores utilicen una escala comparable. Así que primero confirmo que usar --block-size 1in ls -lme da el mismo resultado que antes:

$ ls -l --block-size 1 HISTORY 
-rw-rw-r-- 1 waldyrious waldyrious 581944 Feb 22 10:59 HISTORY

Luego hago lo mismo para ls -sobtener un valor en la misma escala:

$ ls -s --block-size 1 HISTORY 
585728 HISTORY

Diferentes resultados! 581944 ≠ 585728 .

Intenté generar valores comparables al revés, usando -k, pero obtengo:

$ ls -lk HISTORY 
-rw-rw-r-- 1 waldyrious waldyrious 569 Feb 22 10:59 HISTORY
$ ls -sk HISTORY 
572 HISTORY

De nuevo, diferentes resultados, 569 ≠ 572 .

Traté de especificar --si para asegurarme de que ambas opciones usaban la misma escala, sin éxito:

$ ls -lk --si HISTORY 
-rw-rw-r-- 1 waldyrious waldyrious 582k Feb 22 10:59 HISTORY
$ ls -sk --si HISTORY 
586k HISTORY

... de nuevo, diferentes valores: 582k ≠ 586k .

Intenté buscar en la web, pero lo único que pude encontrar que parecía relevante fue esto :

Algunos archivos tienen "agujeros" en ellos, de modo que el uso indicado por ls -s(...) es menor que el tamaño de archivo indicado por ls -l".

(tenga en cuenta que en mis resultados sucede lo contrario: ls -sdevuelve tamaños más grandes que ls -l, no más pequeños).

Mientras tanto, esta página dice que

No hay una manera elegante de detectar agujeros de archivos Unix.

Entonces, ¿cómo puedo lidiar con esta discrepancia? ¿Cuál de estos valores puede considerarse correcto? ¿Podría ser esto un error ls?

waldyrious
fuente

Respuestas:

47

Respuesta corta:

  • ls -l da el tamaño del archivo (= la cantidad de datos que contiene)
  • ls -s --block-size 1 da el tamaño del archivo en el sistema de archivos

Vamos a crear dos archivos:

Un archivo disperso de 128 bytes de longitud (un archivo disperso es un archivo que contiene bloques vacíos, consulte Archivo disperso ):

# truncate -s 128 f_zeroes.img
# hexdump -vC f_zeroes.img 
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000080

Otro archivo con datos aleatorios, también de 128 bytes de tamaño:

# dd if=/dev/urandom of=f_random.img bs=1 count=128
# hexdump -vC f_random.img 
00000000  bc 82 9c 40 04 e3 0c 23  e6 76 79 2f 95 d4 0e 45  |...@...#.vy/...E|
00000010  19 c6 53 fc 65 83 f8 58  0a f7 0e 8f d6 d6 f8 b5  |..S.e..X........|
00000020  6c cf 1b 60 cb ef 06 c6  d0 99 c6 16 3f d3 95 02  |l..`........?...|
00000030  85 1e b7 80 27 93 27 92  d0 52 e8 72 54 25 4d 90  |....'.'..R.rT%M.|
00000040  11 59 a2 d9 0f 79 aa 23  2d 44 3d dd 8d 17 d9 36  |.Y...y.#-D=....6|
00000050  f5 ae 07 a8 c1 b4 cb e1  49 9e bc 62 1b 4f 17 53  |........I..b.O.S|
00000060  95 13 5a 1c 2a 7e 55 b9  69 a5 50 06 98 e7 71 83  |..Z.*~U.i.P...q.|
00000070  5a d0 82 ee 0b b3 91 82  ca 1d d0 ec 24 43 10 5d  |Z...........$C.]|
00000080

Entonces, como puede ver en la representación hexadecimal, ambos archivos tienen la misma cantidad de datos , aunque el contenido es bastante diferente.

Ahora, veamos el directorio:

# ls -ls --block-size 1 f_*
1024 -rw-r--r-- 1 user user 128 Mar 18 15:34 f_random.img
   0 -rw-r--r-- 1 user user 128 Mar 18 15:32 f_zeroes.img
   ^                         ^
   |                         |
Amount which the           Actual file size
files takes on the fs

El primer valor viene dado por la -s --block-size 1opción, es la cantidad de espacio utilizado por el archivo en el sistema de archivos .

Como puede ver, el archivo disperso ocupa cero espacio, ya que el sistema de archivos ( ext3en este caso) fue lo suficientemente inteligente como para reconocer que solo contiene ceros. ¡Además, el archivo con datos aleatorios ocupa 1024 bytes en el disco!

El valor depende de cómo el sistema de archivos subyacente trata los archivos (tamaño de bloque, capacidad de archivo disperso, ...).

En la sexta columna está el tamaño del archivo si lo lees: ¡es la cantidad de datos que contiene el archivo y son 128 bytes para ambos archivos!

phoibos
fuente
1
Presumiblemente, ¿incluso un archivo vacío o un archivo lleno de valores nulos ocuparía espacio en la tabla de asignación de archivos en algún lugar? ¿Por qué no ls -scuenta eso?
Flimm
2
Los metadatos sobre los archivos se almacenan en inodes. Cada sistema de archivos tiene una cantidad limitada de inodos que puede usar. Para ver cuántos inodos libres tiene un sistema de archivos y el tamaño de ellos: sudo tune2fs -l /dev/sdaX|grep Inodeo df -ipara todas las particiones.
phoibos
1
Acabo de encontrar una interesante, de manera no artificial para comprobar esto: .part torrente parecen ser buenos ejemplos de archivos con agujeros: ls -lsh ~/Downloads/torrentsme da, por ejemplo, 92K -rw-r--r-- 1 waldir waldir 350M Sep 15 2012 video.avi.part. Es decir, el 92K, devuelto por la opción -s, es el espacio real que ocupa el archivo, en el sistema de archivos, y 350M, devuelto por la opción -l, es el tamaño completo que tendría el archivo si se descargara por completo (es decir, si todos los bytes, de principio a fin, no fueran cero). Ver lists.freebsd.org/pipermail/freebsd-questions/2012-June/…
waldyrious
14

ls -sle indica el tamaño asignado del archivo, siempre un múltiplo de la unidad de asignación. ls -lIndica el tamaño real. Una forma fácil de probar:

$ echo 1 > sizeTest
$ ls -l --block-size 1 sizeTest 
-rw-rw-r-- 1 g g 2 Mär 18 15:18 sizeTest
$ ls -s --block-size 1 sizeTest 
4096 sizeTest
Guntbert
fuente