Почему ls -l выводит размер, отличный от ls -s?

38

Я не могу понять, почему я получаю следующие результаты:

ls -l говорит мне, что размер данного файла (ИСТОРИЯ) "581944":

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

ls -s говорит, что это "572":

$ ls -s HISTORY
572 HISTORY

Очевидно, мне нужно, чтобы значения использовали сопоставимый масштаб. Итак, сначала я подтверждаю, что использование --block-size 1in ls -lдает мне тот же результат, что и раньше:

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

Затем я делаю то же самое, чтобы ls -sполучить значение в том же масштабе:

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

Разные результаты! 581944 ≠ 585728 .

Я попытался сгенерировать сопоставимые значения наоборот, используя -k, но я получаю:

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

Опять же, разные результаты, 569 ≠ 572 .

Я попытался указать --si, чтобы убедиться, что оба варианта используют один и тот же масштаб, но безрезультатно:

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

... опять же, разные значения: 582k ≠ 586k .

Я пытался искать в Интернете , но единственное , что я мог найти , что казалось уместным было это :

В некоторых файлах есть «дыры», поэтому использование, указанное в ls -s(...), меньше размера файла, указанного в « ls -l

(обратите внимание, что в моих результатах происходит обратное: ls -sвозвращает размеры больше, чем ls -l, не меньше.)

Между тем на этой странице написано, что

элегантного способа обнаружить дыры в файлах Unix не существует.

Итак, как я могу справиться с этим расхождением? Какие из этих значений можно считать правильными? Может ли это быть ошибка в ls?

waldyrious
источник

Ответы:

47

Краткий ответ:

  • ls -l дает размер файла (= объем данных, которые он содержит)
  • ls -s --block-size 1 дает размер файла в файловой системе

Давайте создадим два файла:

Разреженный файл 128 байт длины (разреженный файл представляет собой файл , содержащий пустые блоки, см разреженного файла ):

# 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

Другой файл со случайными данными, также размером 128 байт:

# 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

Итак, как вы можете видеть в шестнадцатеричном представлении, оба файла имеют одинаковый объем данных , хотя их содержание совершенно разное.

Теперь давайте посмотрим на каталог:

# 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

Первое значение задается -s --block-size 1параметром, это объем пространства, используемого файлом в файловой системе .

Как видите, разреженный файл занимает нулевое пространство, поскольку файловая система ( ext3в данном случае) была достаточно умной, чтобы распознать, что она содержит только нули. Также файл со случайными данными занимает на диске 1024 байта!

Значение зависит от того, как основная файловая система обрабатывает файлы (размер блока, возможность разреженного файла, ...).

В шестом столбце указан размер файла, если вы его прочитаете, - это объем данных, содержащихся в файле, и 128 байтов для обоих файлов!

Phoibos
источник
1
Предположительно, даже пустой файл или файл, полный нулевых значений, займет место где-нибудь в таблице размещения файлов? Почему это не ls -sсчитается?
Flimm
2
Метаданные о файлах хранятся в инодах. Каждая файловая система имеет ограниченное количество inode, которые она может использовать. Чтобы узнать, сколько бесплатных инодов имеет файловая система и их размер: sudo tune2fs -l /dev/sdaX|grep Inodeили df -iдля всех разделов.
Phoibos
1
Я только что нашел интересный, без искусственного способа проверить это: торрент .part файлы кажутся хорошими примерами файлов с отверстиями: ls -lsh ~/Downloads/torrentsдает мне, например, 92K -rw-r--r-- 1 waldir waldir 350M Sep 15 2012 video.avi.part. То есть, 92K, возвращаемый параметр -s, является фактическим пространством файла занимает, файловая система мудра, и 350M, возвращаемый параметр -l, является полным размером файл будет иметь , если он был полностью загружен (т.е. если все байты, от начала до конца, были ненулевыми). См. Lists.freebsd.org/pipermail/freebsd-questions/2012-June/…
waldyrious
14

ls -sговорит вам о выделенном размере файла, всегда кратном единице выделения. ls -lговорит реальный размер. Простой способ проверить:

$ 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
источник