How does ls -l
format its output so that column contents line up neatly?
2 Answers
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
-
4Given 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.– user1686Jun 7, 2016 at 4:51 -
@grawity nice. I'd used
findmnt
before, but I never realised it could do this too.– muruJun 7, 2016 at 11:26 -
Also good to know: on Ubuntu/debian
/bin/ls
is part of the package (GNU)coreutils
. You can find this by runningdpkg-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 usingapt-get source <package_name>
– arielfJun 10, 2016 at 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 isscontext_width
, calculated bygooble_file
, the other function I mentioned.– muruJun 6, 2016 at 18:31