3

I am trying to figure out how the program /bin/ls -l calculates the total size (block count) for a directory. By this I mean the output total number that it prints right before the directory contents.

There is a similar question here: https://stackoverflow.com/questions/7401704/what-is-that-total-in-the-very-first-line-after-ls-l but it doesn't fully answer the question nor explain exactly how it is calculated.

I've tried adding the numbers of 512B blocks allocated for all the (non-hidden) files in a directory.  Here is how I am trying to go about it (in C):

 int getBlockSize(char* directory) {
   int size = 0;

   DIR *d;
   struct dirent *dir;
   struct stat fileStat;
   d = opendir(directory);
   if (d) {
       while ((dir = readdir(d)) != NULL) {
           if (dir->d_name[0] != '.') { // Ignore hidden files
               // Create the path to stat
               char info_path[PATH_MAX + 1];
               strcpy(info_path, directory);
               if (directory[strlen(directory) - 1] != '/')
                   strcat(info_path, "/");
               strcat(info_path, dir->d_name);

               stat(info_path, &fileStat);

               size += fileStat.st_blocks;
           }
       }
   }

   return size;
}

However this is giving me a much different number compared to the ls command.

What is 'wrong' with my approach?  How does ls compute the total?

Edit:

To test I made a folder which contains files test_file1.txt and test_file2.txt each containing the text Hello World!. When I run ls -l I get the following output

total 1
-rw-------. 1 aaa111 ugrad 13 Oct 27 13:17 test_file1.txt
-rw-------. 1 aaa111 ugrad 13 Oct 27 13:17 test_file2.txt

However when I run my code using the method above I get

total 2
-rw-------. 1 aaa111 ugrad 13 Oct 27 13:17 test_file1.txt
-rw-------. 1 aaa111 ugrad 13 Oct 27 13:17 test_file2.txt 
2

On Ubuntu, the default ls is GNU ls, which defaults to 1024-byte block size for its “total” line. This explains the difference in output between ls and your approach: your approach shows double the number of blocks because it’s counting 512-byte blocks.

There are various ways to force GNU ls to count in 512-byte blocks (see the link above); the most reliable is to set LS_BLOCK_SIZE:

LS_BLOCK_SIZE=512 ls -l

The other implementation of ls which you’re liable to run into on Linux is BusyBox ls; it also uses a 1024-byte block size for the “total” line, and it can’t be configured to use any other size.

|improve this answer|||||
  • While that works with GNU ls, that doesn't work with busybox ls (probably the most common ls implementation on systems that have Linux as their kernel, though not the type of systems people would use an interactive shell on). Note that with GNU ls, $LS_BLOCK_SIZE takes precedence over $BLOCKSIZE which itself takes precedence over $POSIXLY_CORRECT. – Stéphane Chazelas Oct 1 '19 at 7:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.