Understanding the Difference Between `du -h` and `ls -lh`: File Size vs. Disk Usage in Linux


3 views

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