How does ls -l format its output so neatly?

Solution 1:

The source code of ls is available for browsing online on GNU Savannah. In most cases, the required maximum width is computed (for example, using the mbswidth function for text), and then uses the classic C printf function format specifiers and some manual padding. See, for example, the functions format_user_or_group(), and gobble_file().

TL; DR: there's no "magic", just a lot of grunt computation.


If you want such neat tables for your own output, use column:

$ grep -vE '^#' /etc/fstab
UUID=cdff3742-9d03-4bc1-93e3-ae50708474f2 /               ext4    errors=remount-ro 0       1
/dev/mapper/lvmg-homelvm /home           btrfs   defaults,compress=lzo,space_cache,relatime 0       2
UUID="bb76cd0d-ae1d-4490-85da-1560c32679cd" none    swap sw 0 0
UUID="a264b1b1-cf82-40aa-ab9e-a810cfba169a" /home/muru/arch     btrfs defaults,compress=lzo,space_cache,relatime 0       2

$ grep -vE '^#' /etc/fstab | column -t
UUID=cdff3742-9d03-4bc1-93e3-ae50708474f2    /                ext4   errors=remount-ro                           0  1
/dev/mapper/lvmg-homelvm                     /home            btrfs  defaults,compress=lzo,space_cache,relatime  0  2
UUID="bb76cd0d-ae1d-4490-85da-1560c32679cd"  none             swap   sw                                          0  0
UUID="a264b1b1-cf82-40aa-ab9e-a810cfba169a"  /home/muru/arch  btrfs  defaults,compress=lzo,space_cache,relatime  0  2

Solution 2:

In addition to @muru 's answer, here is the part of the source code which calculates width for right justification of output. :

static void
format_user_or_group (char const *name, unsigned long int id, int width)
{
  size_t len;

  if (name)
    {
      int width_gap = width - mbswidth (name, 0);
      int pad = MAX (0, width_gap);
      fputs (name, stdout);
      len = strlen (name) + pad;

      do
        putchar (' ');
      while (pad--);
    }
  else
    {
      printf ("%*lu ", width, id);
      len = width;
    }

  dired_pos += len + 1;
}

It uses, printf ("%*lu ", width, id); . NOTE : variable field width specifier ‘*’

In this case, it cannot be predicted how large a field width we will need when ls -l is executed, i.e, The names of directories may vary in length . This implies that the field width itself needs to be a variable, for which the program will compute a value.

C uses an asterisk in the position of the field width specifier to indicate to printf that it will find the variable that contains the value of the field width as an additional parameter.

For instance, assume that the current value of width is 5. The statement:

printf ("%*d%*d\n", width, 10, width, 11);

will print: (note the spacing)

   10   11