Como o ls -l formata sua saída tão nitidamente?

19

Como o ls -l formata sua saída para que o conteúdo da coluna seja alinhado perfeitamente?

    
por DK Bose 06.06.2016 / 19:22
fonte

2 respostas

34

O código-fonte de ls está disponível para navegação online em Savana do GNU . Na maioria dos casos, a largura máxima exigida é calculada (por exemplo, usando a função mbswidth para texto) e, em seguida, usa os especificadores de formato de função C printf clássicos e algum preenchimento manual. Veja, por exemplo, as funções format_user_or_group() , e gobble_file() .

TL; DR: não há "magia", apenas um monte de computação grunhida.

Se você quiser essas tabelas perfeitas para sua própria saída, 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
    
por muru 06.06.2016 / 19:49
fonte
17

Além da resposta do @muru , aqui está a parte do source code que calcula width para a justificação correta da saída. :

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

Ele usa printf ("%*lu ", width, id); . NOTA: especificador de largura de campo variável ‘*’

Neste caso, não é possível prever o tamanho da largura de campo necessária quando ls -l é executado, ou seja, os nomes dos diretórios podem variar em tamanho. Isso implica que a própria largura do campo precisa ser uma variável , para a qual o programa calculará um valor .

C usa um na posição do especificador de largura de campo para indicar ao printf que ele encontrará a variável que contém o valor da largura do campo como um parâmetro adicional.

Por exemplo, suponha que o valor atual da largura seja 5. A instrução:

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

irá imprimir: (note o espaçamento)

   10   11
    
por Severus Tux 13.04.2017 / 14:25
fonte

Tags