19

How does ls -l format its output so that column contents line up neatly?

terminal

34

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
  • 4
    Given that you used /etc/fstab as an example, I can't help but suggest findmnt --fstab. The util-linux package even comes with a library "libsmartcols" (previously libtt) which it uses in findmnt, lsblk, etc. to print an aligned table. – grawity Jun 7 '16 at 4:51
  • @grawity nice. I'd used findmnt before, but I never realised it could do this too. – muru Jun 7 '16 at 11:26
  • Also good to know: on Ubuntu/debian /bin/ls is part of the package (GNU) coreutils. You can find this by running dpkg-query -S /bin/ls. Once you know the package name, you can download any Ubuntu package exact source code from which the binary is built (this is important) by using apt-get source <package_name> – arielf Jun 10 '16 at 17:17
17

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
  • The width here is scontext_width, calculated by gooble_file, the other function I mentioned. – muru Jun 6 '16 at 18:31

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.