Pourquoi ls -l affiche-t-il une taille différente de celle de ls -s?

38

Je n'arrive pas à comprendre pourquoi j'obtiens les résultats suivants:

ls -l me dit que la taille d'un fichier donné (HISTORY) est "581944":

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

ls -s dit que c'est "572":

$ ls -s HISTORY
572 HISTORY

Je dois évidemment faire en sorte que les valeurs utilisent une échelle comparable. Je confirme donc d'abord que l'utilisation de --block-size 1in ls -lme donne le même résultat qu'auparavant:

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

Ensuite, je fais la même chose pour ls -sobtenir une valeur de la même échelle:

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

Des résultats différents! 581944 ≠ 585728 .

J'ai essayé de générer des valeurs comparables dans l'autre sens, en utilisant -k, mais je reçois:

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

Encore une fois, des résultats différents, 569 572 .

J'ai essayé de spécifier --si pour m'assurer que les deux options utilisaient la même échelle, mais en vain:

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

... encore une fois, différentes valeurs: 582k 6 586k .

J'ai essayé de chercher sur le Web, mais la seule chose qui me semblait pertinente était la suivante :

Certains fichiers comportent des "trous", de sorte que l'utilisation indiquée par ls -s(...) est inférieure à la taille du fichier indiqué par ls -l. "

(Notez que dans mes résultats, l'inverse se produit: ls -srenvoie des tailles plus grandes que ls -l, pas plus petites.)

En attendant, cette page dit que

il n'y a pas de moyen élégant de détecter les trous de fichiers Unix.

Alors, comment puis-je traiter cette différence? Laquelle de ces valeurs peut être considérée comme correcte? Est-ce que cela pourrait être un bug ls?

Waldyrious
la source

Réponses:

47

Réponse courte:

  • ls -l donne la taille du fichier (= la quantité de données qu'il contient)
  • ls -s --block-size 1 donne la taille du fichier sur le système de fichiers

Créons deux fichiers:

Un fichier fragmenté de 128 octets (un fichier fragmenté est un fichier contenant des blocs vides, voir Fichier fragmenté ):

# 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

Un autre fichier avec des données aléatoires, également de 128 octets:

# 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

Ainsi, comme vous pouvez le voir dans la représentation hexadécimale, les deux fichiers contiennent la même quantité de données , bien que le contenu soit assez différent.

Regardons maintenant le répertoire:

# 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

La première valeur est donnée par l' -s --block-size 1option, il s'agit de la quantité d'espace utilisée par le fichier sur le système de fichiers .

Comme vous pouvez le constater, le fichier fragmenté n'occupe aucun espace, car le système de fichiers ( ext3dans ce cas) était suffisamment intelligent pour reconnaître qu'il ne contenait que des zéros. En outre, le fichier contenant des données aléatoires occupe 1024 octets sur le disque!

La valeur dépend de la manière dont le système de fichiers sous-jacent traite les fichiers (taille de bloc, capacité de fichier fragmenté, ...).

Dans la sixième colonne est la taille du fichier si vous voulez le lire - c'est la quantité de données que contient le fichier et c'est 128 octets pour les deux fichiers!

phoibos
la source
1
Vraisemblablement, même un fichier vide ou un fichier contenant des valeurs nulles prendrait quelque part de la place dans la table d’allocation de fichiers? Pourquoi ne ls -scompte pas ça?
Flimm
2
Les métadonnées sur les fichiers sont stockées dans des inodes. Chaque système de fichiers ne peut utiliser qu'une quantité limitée d'inodes. Pour voir le nombre d'inodes libres d'un système de fichiers et leur taille:, sudo tune2fs -l /dev/sdaX|grep Inodeou df -ipour toutes les partitions.
Phoibos
1
Je viens de trouver un moyen intéressant et non artificiel de vérifier cela: les fichiers .part torrent semblent être de bons exemples de fichiers avec des trous: ls -lsh ~/Downloads/torrentsme donne, par exemple 92K -rw-r--r-- 1 waldir waldir 350M Sep 15 2012 video.avi.part,. Autrement dit, le 92K, retourné par l'option -s, est l'espace réel du fichier prend, système de fichiers sage et 350m, retourné par l'option -l, est la taille complète du fichier serait que si elle a été complètement téléchargé (c. -à- si tous les octets, du début à la fin, étaient non nuls). Voir lists.freebsd.org/pipermail/freebsd-questions/2012-June/…
waldyrious
14

ls -svous indique la taille allouée du fichier, toujours un multiple de l'unité d'allocation. ls -lindique la taille réelle. Un moyen facile de tester:

$ 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
la source