Wie formatiert ls -l seine Ausgabe so ordentlich?

19

Wie ls -lformatiert man die Ausgabe so, dass der Spalteninhalt ordentlich ausgerichtet ist?

Terminal

Gerechtigkeit für Monica
quelle

Antworten:

34

Der Quellcode von kann lsonline in GNU Savannah durchsucht werden . In den meisten Fällen wird die erforderliche maximale Breite berechnet (z. B. mithilfe der mbswidthFunktion für Text). Anschließend werden die klassischen printfFormatbezeichner für C- Funktionen und einige manuelle Auffüllungen verwendet. Siehe z. B. die Funktionen format_user_or_group()und gobble_file().

TL; DR: Es gibt keine "Magie", nur viel Grunzen.


Wenn Sie solche übersichtlichen Tabellen für Ihre eigene Ausgabe benötigen, verwenden Sie 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
muru
quelle
4
Angesichts der Tatsache, dass Sie / etc / fstab als Beispiel verwendet haben, kann ich nur vorschlagen findmnt --fstab. Das Paket util-linux enthält sogar eine Bibliothek "libsmartcols" (früher libtt), die in findmnt, lsblk usw. zum Drucken einer ausgerichteten Tabelle verwendet wird.
Grawity
@grawity nett. Ich hatte es schon einmal benutzt findmnt, aber ich habe nie bemerkt, dass es das auch kann.
muru
Ebenfalls gut zu wissen: Auf Ubuntu / Debian /bin/lsist ein Teil des Pakets (GNU) coreutils. Sie können dies finden, indem Sie ausführen dpkg-query -S /bin/ls. Sobald Sie den Paketnamen kennen, können Sie jeden Ubuntu-Paket-genauen Quellcode herunterladen, aus dem die Binärdatei besteht (dies ist wichtig), indem Sieapt-get source <package_name>
arielf
17

Zusätzlich zu @murus Antwort ist hier der Teil des Quellcodes, der die widthrichtige Rechtfertigung der Ausgabe berechnet . :

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

Es verwendet, printf ("%*lu ", width, id);. HINWEIS: Variabler Feldbreitenbezeichner '*'

In diesem Fall kann nicht vorhergesagt werden, wie groß die Feldbreite sein wird, die bei der ls -lAusführung benötigt wird, dh die Namen der Verzeichnisse können unterschiedlich lang sein. Dies impliziert, dass die Feldbreite selbst eine Variable sein muss , für die das Programm einen Wert berechnet .

C verwendet ein Sternchen an der Position des Feldbreitenspezifizierers, um zu drucken, dass es die Variable findet, die den Wert der Feldbreite als zusätzlichen Parameter enthält.

Angenommen, der aktuelle Wert für width ist 5. Die Anweisung:

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

wird gedruckt: (Abstand beachten)

   10   11
Severus Tux
quelle
Das widthhier ist scontext_width, berechnet von gooble_file, die andere Funktion, die ich erwähnt habe.
muru