Jak ls -l tak starannie formatuje dane wyjściowe?


Odpowiedzi:


34

Kod źródłowy lsjest dostępny do przeglądania online na GNU Savannah . W większości przypadków obliczana jest wymagana maksymalna szerokość (na przykład przy użyciu mbswidthfunkcji tekstu), a następnie używane są klasyczne printfspecyfikatory formatu funkcji C i niektóre ręczne wypełnianie. Zobacz na przykład funkcje format_user_or_group()i gobble_file().

TL; DR: nie ma „magii”, po prostu dużo obliczeń.


Jeśli chcesz takie porządne tabele dla własnych wyników, użyj 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
Biorąc pod uwagę, że użyłeś / etc / fstab jako przykładu, nie mogę się powstrzymać od sugestii findmnt --fstab. Pakiet util-linux zawiera nawet bibliotekę „libsmartcols” (wcześniej libtt), której używa w findmnt, lsblk itp. Do drukowania wyrównanej tabeli.
grawity

@grawity nicea. Używałem findmntwcześniej, ale nigdy nie zdawałem sobie sprawy, że to też może zrobić.
muru

Warto również wiedzieć: na Ubuntu / debian /bin/lsjest częścią pakietu (GNU) coreutils. Możesz to znaleźć, uruchamiając dpkg-query -S /bin/ls. Znając nazwę pakietu, możesz pobrać dowolny kod źródłowy pakietu Ubuntu, z którego zbudowany jest plik binarny (jest to ważne), używającapt-get source <package_name>
arielf

17

Oprócz odpowiedzi @muru , tutaj jest część kodu źródłowego, która oblicza widthprawidłowe uzasadnienie wyniku. :

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

To wykorzystuje printf ("%*lu ", width, id);. UWAGA: specyfikator zmiennej szerokości pola „*”

W takim przypadku nie można przewidzieć, jak dużą szerokość pola będziemy potrzebować podczas ls -lwykonywania, tj. Nazwy katalogów mogą mieć różną długość. Oznacza to, że sama szerokość pola musi być zmienną , dla której program obliczy wartość .

C używa gwiazdki w pozycji specyfikatora szerokości pola, aby wskazać printf, że znajdzie zmienną zawierającą wartość szerokości pola jako dodatkowy parametr.

Załóżmy na przykład, że bieżąca wartość szerokości wynosi 5. Instrukcja:

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

wydrukuje: (zwróć uwagę na odstępy)

   10   11

widthTu jest scontext_width, oblicza się gooble_file, z drugiej funkcji wspominałem.
muru
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.