Dlaczego ls -l wyświetla inny rozmiar niż ls -s?

38

Nie mogę zrozumieć, dlaczego otrzymuję następujące wyniki:

ls -l mówi mi, że rozmiar danego pliku (HISTORIA) to „581944”:

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

ls -s mówi, że jest to „572”:

$ ls -s HISTORY
572 HISTORY

Oczywiście muszę zastosować wartości w porównywalnej skali. Najpierw potwierdzam, że użycie --block-size 1in ls -ldaje taki sam wynik jak poprzednio:

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

Następnie robię to samo, aby ls -suzyskać wartość w tej samej skali:

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

Różne wyniki! 581944 585728 .

Próbowałem wygenerować porównywalne wartości na odwrót, używając -k, ale otrzymuję:

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

Ponownie różne wyniki, 569 ≠ 572 .

Próbowałem podać --si, aby upewnić się, że obie opcje używają tej samej skali, ale bezskutecznie:

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

... znowu, różne wartości: 582 tys . ≠ 586 tys .

Próbowałem przeszukać sieć, ale jedyne, co wydawało mi się istotne, to :

Niektóre pliki mają „dziury”, więc użycie wymienione przez ls -s(...) jest mniejsze niż rozmiar pliku wymienione przez ls -l. ”

(zauważ, że w moich wynikach dzieje się odwrotnie: ls -szwraca rozmiary większe niż ls -l, nie mniejsze).

Tymczasem ta strona to mówi

nie ma eleganckiego sposobu na wykrycie dziur w plikach uniksowych.

Jak więc poradzić sobie z tą rozbieżnością? Które z tych wartości można uznać za prawidłowe? Czy to może być błąd ls?

waldyrious
źródło

Odpowiedzi:

47

Krótka odpowiedź:

  • ls -l podaje rozmiar pliku (= ilość danych, które zawiera)
  • ls -s --block-size 1 podaje rozmiar pliku w systemie plików

Utwórzmy dwa pliki:

Plik rzadki o długości 128 bajtów (plik rzadki to plik zawierający puste bloki, patrz Plik rzadki ):

# 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

Kolejny plik z losowymi danymi, również o wielkości 128 bajtów:

# 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

Tak więc, jak widać w reprezentacji szesnastkowej, oba pliki zawierają tę samą ilość danych , chociaż zawartość jest zupełnie inna.

Teraz spójrzmy na katalog:

# 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

Pierwsza wartość jest podana przez -s --block-size 1opcję, jest to ilość miejsca używanego przez plik w systemie plików .

Jak widać, rzadki plik zajmuje zero miejsca, ponieważ system plików ( ext3w tym przypadku) był wystarczająco inteligentny, aby rozpoznać, że zawiera tylko zera. Ponadto plik z losowymi danymi zajmuje 1024 bajty na dysku!

Wartość zależy od tego, w jaki sposób system plików traktuje pliki (rozmiar bloku, ograniczone możliwości plików, ...).

W szóstej kolumnie znajduje się rozmiar pliku, jeśli go przeczytasz - jest to ilość danych, które zawiera plik i 128 bajtów dla obu plików!

phoibos
źródło
1
Przypuszczalnie nawet pusty plik lub plik pełen wartości zerowych zajmowałby gdzieś miejsce w tabeli alokacji plików? Dlaczego to się nie ls -sliczy?
Flimm
2
Metadane dotyczące plików są przechowywane w i-węzłach. Każdy system plików ma ograniczoną liczbę i-węzłów, z których może korzystać. Aby sprawdzić liczbę wolnych i-węzłów w systemie plików i ich rozmiar: sudo tune2fs -l /dev/sdaX|grep Inodelub df -idla wszystkich partycji.
phoibos,
1
Właśnie znalazłem ciekawy, nie-sztuczny sposób na sprawdzenie tego: pliki .part torrent wydają się być dobrymi przykładami plików z dziurami: ls -lsh ~/Downloads/torrentsna przykład daje mi 92K -rw-r--r-- 1 waldir waldir 350M Sep 15 2012 video.avi.part. Oznacza to, że 92K, zwrócone przez opcję -s, to rzeczywiste miejsce, które zajmuje plik, pod względem systemu plików, a 350M, zwrócone przez opcję -l, to pełny rozmiar pliku, który miałby , gdyby został całkowicie pobrany (tj. jeśli wszystkie bajty, od początku do końca, były niezerowe). Zobacz lists.freebsd.org/pipermail/freebsd-questions/2012-June/…
waldyrious
14

ls -sinformuje o przydzielonym rozmiarze pliku, zawsze wielokrotności jednostki alokacji. ls -lmówi rzeczywisty rozmiar. Łatwy sposób przetestować:

$ 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
źródło