Lo hice y lo entendí

El blog de Vicente Navarro
21 mar

La variable LC_COLLATE y la ordenación en la salida del comando “ls”

Tras las últimas instalaciones que he hecho de Debian, había una cosa que me disgustaba mucho Cuando ejecutaba “ls -la”, el comando me ordenaba las entradas escondidas (precedidas de punto) como si no lo tuvieran. Por ejemplo, si tenía un fichero llamado mi_fichero en el $HOME de root, el “ls -la” me devolvía lo siguiente:

rwxr-xr-x  8 root root    4096 2007-03-21 20:51 .
drwxr-xr-x 20 root root    4096 2006-11-18 11:34 ..
-rw-------  1 root root    6805 2007-03-19 19:56 .bash_history
-rw-r--r--  1 root root     535 2006-11-11 11:10 .bashrc
drwxr-xr-x  2 root root    4096 2006-11-21 21:16 .config
-rw-r--r--  1 root root  605281 2006-11-21 21:16 .fonts.cache-1
-rw-r--r--  1 root root       0 2007-03-21 20:51 mi_fichero
-rw-r--r--  1 root root     110 2004-11-10 17:10 .profile
-rw-------  1 root root    4394 2007-03-14 21:13 .viminfo
-rw-------  1 root root       0 2006-10-13 19:31 .Xauthority
-rw-------  1 root root     135 2006-10-13 19:31 .xsession-errors

cuando yo hubiera querido que me devolviera, como estoy acostumbrado, lo siguiente, para poder ver fácilmente qué archivos son los míos y cuáles son los de configuración (unos abajo y otros arriba del listado):

rwxr-xr-x  8 root root    4096 2007-03-21 20:51 .
drwxr-xr-x 20 root root    4096 2006-11-18 11:34 ..
-rw-------  1 root root    6805 2007-03-19 19:56 .bash_history
-rw-r--r--  1 root root     535 2006-11-11 11:10 .bashrc
drwxr-xr-x  2 root root    4096 2006-11-21 21:16 .config
-rw-r--r--  1 root root  605281 2006-11-21 21:16 .fonts.cache-1
-rw-r--r--  1 root root     110 2004-11-10 17:10 .profile
-rw-------  1 root root    4394 2007-03-14 21:13 .viminfo
-rw-------  1 root root       0 2006-10-13 19:31 .Xauthority
-rw-------  1 root root     135 2006-10-13 19:31 .xsession-errors
-rw-r--r--  1 root root       0 2007-03-21 20:51 mi_fichero

Me costó bastante encontrar la solución, pero al final di con ella. La respuesta está en la variable de entorno LC_COLLATE, que afecta a la ordenación (collate según Wordreference significa recopilar pero me parece que tiene más que ver con ordenar en este contexto). Dicha variable es parte de los locales o internacionalización de la glibc y afecta a cómo las funciones de la libc strcoll y strxfrm hacen su trabajo.

Por ejemplo, si abrimos el fichero /usr/share/i18n/locales/es_ES veremos las reglas de ordenación para es_ES que indican que una á va justo después de una a y que una ñ va justo detrás de una n. Antes de 1994 también tendríamos que haber tenido reglas para que una palabra que comenzara por ch o ll fuera detrás de coche o lobo respectivamente:

LC_COLLATE
copy "iso14651_t1"
 
collating-symbol  <ntilde>
 
reorder-after <n>
<ntilde>
 
reorder-after <U006E>
<U00F1> <ntilde>;<TIL>;<MIN>;IGNORE
reorder-after <U004E>
<U00D1> <ntilde>;<TIL>;<CAP>;IGNORE
 
reorder-end
 
END LC_COLLATE

El tema es que la salida del comando locale en mis sistemas era (siempre intento usar todos los sistemas operativos en inglés para poder buscar más fácilmente posibles mensajes de error):

# locale
LANG=en_US.ISO-8859-15
LC_CTYPE="en_US.ISO-8859-15"
LC_NUMERIC="en_US.ISO-8859-15"
LC_TIME="en_US.ISO-8859-15"
LC_COLLATE="en_US.ISO-8859-15"
LC_MONETARY="en_US.ISO-8859-15"
LC_MESSAGES="en_US.ISO-8859-15"
LC_PAPER="en_US.ISO-8859-15"
LC_NAME="en_US.ISO-8859-15"
LC_ADDRESS="en_US.ISO-8859-15"
LC_TELEPHONE="en_US.ISO-8859-15"
LC_MEASUREMENT="en_US.ISO-8859-15"
LC_IDENTIFICATION="en_US.ISO-8859-15"
LC_ALL=

Como esa LC_COLLATE no me servía para obtener la salida deseada puse en el .bashrc:

export LC_COLLATE=C

¡y ahora ya tengo la salida de “ls -la” deseada! A expensas, eso sí, de que acentos, mayúsculas, etc. sean ordenados de forma menos lógica lingüisticamente, pero más lógica informáticamente.

Algunos ejemplos más en los que vemos que según sea el valor LC_COLLATE los acentos, las eñes, las mayúsculas o los ficheros que comienzan por punto se ordenan de forma lógica o según la tabla de caracteres:

# export LC_COLLATE=es_ES
# ls -a
.  ..  AA  aá  ae  BB  CC  DD  EE  .escondido  FF  nñ  np
# export LC_COLLATE=C
# ls -a
.  ..  .escondido  AA  BB  CC  DD  EE  FF  ae  aá  np  nñ

Entradas relacionadas

2 Comentarios a “La variable LC_COLLATE y la ordenación en la salida del comando “ls””

Tema LHYLE09, creado por Vicente Navarro