When working with file sizes in Linux, two commonly used commands are du -h
and ls -lh
. While both display file sizes, they often show different values, leading to confusion. This article explains the technical differences and why these discrepancies occur.
The ls -lh
command displays the logical size of a file, which is the actual number of bytes the file contains. For example:
$ ls -lh example.txt
-rw-r--r-- 1 user user 1.2K Mar 10 10:00 example.txt
Here, 1.2K
represents the exact size of the data in the file.
The du -h
command shows the physical disk space allocated to the file, which depends on the filesystem's block size. For example:
$ du -h example.txt
4.0K example.txt
In this case, 4.0K
indicates the space reserved on disk, which is typically a multiple of the filesystem's block size (e.g., 4KB).
The difference arises because filesystems allocate space in fixed-size blocks. Even if a file is only 1 byte, it will occupy an entire block (e.g., 4KB). This is why du
often reports larger sizes than ls
.
Let's create a small file and compare the outputs:
$ echo "Hello" > test.txt
$ ls -lh test.txt
-rw-r--r-- 1 user user 6 Mar 10 10:05 test.txt
$ du -h test.txt
4.0K test.txt
Here, ls
shows 6 bytes (the actual content), while du
shows 4KB (the allocated block).
- Use
ls -lh
when you need the exact file size for operations like transfers or checksums. - Use
du -h
when assessing disk usage or storage requirements.
To understand why du
behaves this way, check your filesystem's block size:
$ stat -f -c "%s" .
4096
This shows a 4KB block size, explaining the du
output above.
While ls -lh
and du -h
both report file sizes, they serve different purposes. ls
gives the logical size, while du
shows physical disk allocation. Understanding this distinction is crucial for accurate storage management.
When working with file sizes in Unix/Linux systems, you'll encounter two fundamentally different metrics:
# Example showing discrepancy
$ ls -lh myfile.txt
-rw-r--r-- 1 user group 1.2K Dec 10 10:00 myfile.txt
$ du -h myfile.txt
4.0K myfile.txt
Modern filesystems (ext4, XFS, etc.) use block allocation for storage efficiency. Even if your file contains just 1 byte:
- Logical size (reported by
ls
): Actual content size (1 byte) - Physical size (reported by
du
): 4KB (typical block size)
# Check your filesystem block size
$ stat -f -c "%S" .
4096
# View both metrics simultaneously
$ ls -lhs
4.0K -rw-r--r-- 1 user group 1.2K Dec 10 10:00 myfile.txt
Consider these practical scenarios:
# Database applications with sparse files
$ truncate -s 1G largefile.db
$ ls -lh largefile.db
-rw-r--r-- 1 user group 1.0G Dec 10 10:05 largefile.db
$ du -h largefile.db
0 largefile.db
For precise analysis, use these commands:
# Show allocated blocks
$ debugfs -R "stat <$(stat -c %i myfile.txt)>" /dev/sda1
# View sparse file maps
$ filefrag -v largefile.db
Understanding this distinction helps when:
- Packaging applications with many small files
- Configuring database storage engines
- Implementing file-based caching systems