Як ls -l так чітко відформатує вихід?


Відповіді:


34

Вихідний код lsдоступний для перегляду в Інтернеті в GNU Savannah . У більшості випадків необхідна максимальна ширина обчислюється (наприклад, використовуючи mbswidthфункцію для тексту), а потім використовує класичні printfспецифікатори формату C та деякі ручні накладки. Див., Наприклад, функції format_user_or_group()та gobble_file().

TL; ДР: немає ніякої "магії", просто безліч бурхливих обчислень.


Якщо ви хочете такі акуратні таблиці для власного виводу, використовуйте 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
Зважаючи на те, що ви використовували / etc / fstab як приклад, я не можу не запропонувати findmnt --fstab. Пакет util-linux навіть постачається з бібліотекою "libsmartcols" (раніше libtt), яку він використовує у findmnt, lsblk тощо для друку вирівняної таблиці.
grawity

@grawity приємно. Я раніше використовував findmnt, але ніколи не розумів, що це теж може зробити.
муру

Також добре знати: Ubuntu / debian /bin/lsє частиною пакету (GNU) coreutils. Ви можете знайти це, запустивши dpkg-query -S /bin/ls. Коли ви дізнаєтесь назву пакета, ви можете завантажити будь- який точний вихідний код пакета Ubuntu, з якого побудований двійковий код (це важливо), використовуючиapt-get source <package_name>
arielf

17

Окрім відповіді @muru , ось частина вихідного коду, яка розраховує widthдля правильного обґрунтування виводу. :

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;
}

Він використовує printf ("%*lu ", width, id);. ПРИМІТКА: змінний специфікатор ширини поля '*'

У цьому випадку не можна передбачити, яка велика ширина поля нам знадобиться при ls -lвиконанні, тобто назви каталогів можуть відрізнятися за довжиною. Це означає, що сама ширина поля повинна бути змінною , для якої програма обчислить значення .

C використовує зірочку в положенні специфікатора ширини поля, щоб вказати printf, що він знайде змінну, яка містить значення ширини поля як додатковий параметр.

Наприклад, припустимо, що поточне значення ширини дорівнює 5. Виписка:

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

надрукує: (зверніть увагу на інтервал)

   10   11

Ось widthтут scontext_width, обчислено gooble_file, за іншою функцією, яку я згадав.
муру
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.