¿Cómo ls -l formatea su salida tan claramente?

19

¿Cómo forma ls -l su resultado para que los contenidos de las columnas se alineen perfectamente?

    
pregunta DK Bose 06.06.2016 - 17:22

2 respuestas

34

El código fuente de ls está disponible para navegar en línea en GNU Savannah . En la mayoría de los casos, se calcula el ancho máximo requerido (por ejemplo, usando la función mbswidth para el texto), y luego se usan los clasificadores de formato de función C printf clásicos y algunos rellenos manuales. Ver, por ejemplo, las funciones format_user_or_group() , y gobble_file() .

TL; DR: no hay "magia", solo mucha computación gruñona.

Si quiere tablas tan ordenadas para su propia salida, 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
    
respondido por el muru 06.06.2016 - 17:49
17

Además de la respuesta de @muru , esta es la parte del source code que calcula width para la justificación correcta de la salida. :

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

Utiliza, printf ("%*lu ", width, id); . NOTA: especificador de ancho de campo variable '*'

En este caso, no se puede predecir qué ancho de ancho de campo necesitaremos cuando se ejecute ls -l , es decir, los nombres de los directorios pueden variar en longitud. Esto implica que el ancho del campo en sí debe ser una variable , para lo cual el programa calculará un valor .

C usa un asterisco en la posición del especificador de ancho de campo para indicar a printf que encontrará la variable que contiene el valor del ancho del campo como un parámetro adicional.

Por ejemplo, supongamos que el valor actual del ancho es 5. La afirmación:

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

se imprimirá: (tenga en cuenta el espacio)

   10   11
    
respondido por el Severus Tux 13.04.2017 - 12:25

Lea otras preguntas en las etiquetas