Comment ls -l formate-t-il si bien sa sortie?

19

Comment formate-t-il ls -lsa sortie pour que le contenu des colonnes soit parfaitement aligné?

Terminal

Justice pour Monica
la source

Réponses:

34

Le code source de lsest disponible pour la navigation en ligne sur GNU Savannah . Dans la plupart des cas, la largeur maximale requise est calculée (par exemple, en utilisant la mbswidthfonction pour le texte), puis utilise les printfspécificateurs de format de fonction C classiques et un remplissage manuel. Voir, par exemple, les fonctions format_user_or_group()et gobble_file().

TL; DR: il n'y a pas de "magie", juste beaucoup de calculs de grognement.


Si vous voulez de telles tables soignées pour votre propre sortie, utilisez 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
la source
4
Étant donné que vous avez utilisé / etc / fstab comme exemple, je ne peux m'empêcher de suggérer findmnt --fstab. Le paquet util-linux est même livré avec une bibliothèque "libsmartcols" (anciennement libtt) qu'il utilise dans findmnt, lsblk, etc. pour imprimer une table alignée.
grawity
@grawity nice. J'en avais déjà utilisé findmnt, mais je n'avais jamais réalisé que ça pouvait faire ça aussi.
muru
Aussi bon à savoir: sur Ubuntu / debian /bin/lsfait partie du paquet (GNU) coreutils. Vous pouvez le trouver en exécutant dpkg-query -S /bin/ls. Une fois que vous connaissez le nom du package, vous pouvez télécharger tout code source exact du package Ubuntu à partir duquel le binaire est construit (c'est important) en utilisantapt-get source <package_name>
arielf
17

En plus de la réponse de @muru , voici la partie du code source qui calcule la widthbonne justification de la sortie. :

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

Il utilise printf ("%*lu ", width, id);. REMARQUE: spécificateur de largeur de champ variable '*'

Dans ce cas, il n'est pas possible de prédire la largeur d'une zone dont nous aurons besoin lors de l' ls -lexécution, c'est-à-dire que les noms des répertoires peuvent varier en longueur. Cela implique que la largeur du champ lui-même doit être une variable , pour laquelle le programme calculera une valeur .

C utilise un astérisque à la position du spécificateur de largeur de champ pour indiquer à printf qu'il trouvera la variable qui contient la valeur de la largeur de champ comme paramètre supplémentaire.

Par exemple, supposons que la valeur actuelle de largeur est 5. L'instruction:

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

imprimera: (notez l'espacement)

   10   11
Severus Tux
la source
L' widthici est scontext_width, calculé par gooble_file, l' autre fonction que j'ai mentionnée.
muru