3

As far as i know the ls command with the "-s" option print the file size in blocks , ls uses the 1024 as block size , but i noticed something weird .

For better understanding consider the following output of ls -ls command:

12 -rw-r--r--. 1 root root 10240 Jul 15 19:22 z

the file size is 10240 bytes and the block size is 1024 so the number of blocks for this file is 10240/1024 = 10 blocks , but why ls shows 12 blocks?

Regards

Seamus
  • 2,925

3 Answers3

4

What ls actually reports here is the size of the blocks allocated for the file. That size is 12 kB.

This size was traditionally reported in “blocks” of 512 B, because on ancient Unix systems, it was indeed a number of 512-byte blocks. But the block size depends on the filesystem, whereas ls uses the same unit regardless. GNU tools use 1 kB instead of 512 B as the unit, because kilobytes are more meaningful to humans than half-kilobytes.

Ext4 and several other common filesystems default to 4 kB blocks. So a 10240-byte file occupies 3 blocks, and the size of those 3 blocks is 12 kB.

See also file block size - difference between stat and ls and Difference between block size and cluster size.

2

This is a great question: After reading Gilles' answer, I was forced to read man ls, and ls --help closely because I was quite sure his answer was wrong. Instead, I offer this answer to prove he is correct! :P

Your result from ls -ls on a 1024-byte file was:

12 -rw-r--r--. 1 root root 10240 Jul 15 19:22 z

If we believe man ls, and your assertion that the file in question is 10,240 bytes, then this result tells us that the size of the file is 12 blocks, but that result does not tell us the size of those blocks. If we refer to the relevant passages from man ls to learn the block size, we come away empty-handed, more or less.

The relevant passages from man ls seem to be the following:

--block-size=SIZE
       with -l, scale sizes by SIZE when printing them; e.g., '--block size=M'; see SIZE format below

-k, --kibibytes default to 1024-byte blocks for disk usage; used only with -s and per directory totals

-s, --size print the allocated size of each file, in blocks

The SIZE argument is an integer and optional unit (example: 10K is 10*1024). Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers of 1000).

Taking nothing on faith:

Create a 10,240-byte file as follows:

fallocate -l 10240 lstest.txt

Verify:

wc -c lstest.txt
10240 lstest.txt
ls -l
  12 -rw-r--r-- 1 pi pi   10240 Jan  4 12:09 lstest.txt  
ls -ls
  12 -rw-r--r-- 1 pi pi   10240 Jan  4 12:09 lstest.txt 
ls -lks 
  12 -rw-r--r-- 1 pi pi   10240 Jan  4 02:09 lstest.txt 
ls -ls --kibibytes 
  12 -rw-r--r-- 1 pi pi   10240 Jan  4 02:09 lstest.txt

And this seems, as you've said, WEIRD because taking the documentation at face value, 12 * 1,024 = 12,288 bytes - which is greater than 10,240 bytes.

But there's a way out:

Consider three things:

  1. The -s option reports the allocation not the file size (ref man ls)
  2. Block size is an abstraction defined in the file system. It's not a physical quantity, but it's efficient to align the block size with the Advanced Format sector size of 4,096 bytes. All HDDs manufactured since Jan 2011 comply with the Advanced Format standard.
  3. We can determine the block size of our file system:
stat -fc %s .     
# or, if you prefer:
stat -fc %s lstest.txt
# which is, in both cases (on my ext3 filesystem):
4096

Some answers, at last

1. Conclusion from all the above: ls has no knowledge of the block size used by the file system.
2. If we know the block size, we must share that with ls to get the correct answer:
ls -ls --block-size=4K 
3 -rw-r--r-- 1 pi pi    3 Jan  4 02:09 lstest.txt

Note that 3 * 4,096 = 12,288 bytes. Also note that the block size (4,096 bytes) is a kind of quantum of storage for a block device; i.e. the smallest amount by which a storage allocation can change. It now becomes clear that 12,288 bytes is in fact the required allocation in bytes. However to get the correct answer in blocks, as per man ls, ls must be informed of the system's block size via the --block-size=4K option.

3. Gilles' answer was correct
Ruminations:

It seems to me that man ls is not as clear as it could be. Perhaps it should be revised to state that it does does not know the file system block size?

Better yet, perhaps ls could be revised to get the block size from the system? After all - stat is also part of GNU coreutils 8.30.

Seamus
  • 2,925
1

Because it has become default, it is highly probable that the underlying filesystem has a 4k blocksize. Hence, your 10.240 bytes file will need 3 (ceil(10.240/4096)) filesystem blocks. 3 blocks of 4k each being reported as 3 * 4 = 12 1k blocks

MC68020
  • 7,981