¿Cómo puedo hacer que "ls" muestre archivos de puntos primero sin dejar de distinguir entre mayúsculas y minúsculas?

21

Cree los siguientes archivos en un directorio.

$ touch .a .b a b A B 你好嗎

Mi lsorden predeterminada ignora la presencia de puntos iniciales, mezclándolos con los otros archivos.

$ ls -Al
total 0
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 A
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 B
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:06 你好嗎

Yo puedo cambiar LC_COLLATE a poner en primer lugar los dotfiles.

$ LC_COLLATE=C ls -Al
total 0
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 A
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 B
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:06 你好嗎

Por desgracia, esto hace que el orden de clasificación entre mayúsculas y minúsculas, es decir, Ay Bpreceden ay b. ¿Hay alguna manera de imprimir archivos de puntos primero sin dejar de distinguir entre mayúsculas Ay minúsculas ( y apreceder By b)?

Editar: intentando modificar LC_COLLATE

Ninguna de las respuestas hasta ahora replica completamente la funcionalidad de lsfácilmente. Posiblemente, podría incluir algunos de ellos en una función, pero esto tendría que incluir un código detallado sobre (p. Ej.) Cómo trabajar sin argumento frente a proporcionar un directorio como argumento. O cómo lidiar con una -dbandera explícita .

Alternativamente, pensé que tal vez podría haber una mejor LC_COLLATEpara usar. Sin embargo, parece que no puedo hacer que eso funcione. Actualmente estoy usando LC_COLLATE="en_AU.UTF-8". Lo comprobé /usr/share/i18n/locales/en_AU(aunque no estoy seguro de si este es el archivo correcto, ya que no puedo ver ninguna referencia UTF-8); Encontré lo siguiente.

LC_COLLATE
copy "iso14651_t1"
END LC_COLLATE

/usr/share/i18n/locales/iso14651_t1contiene copy "iso14651_t1_common". Finalmente /usr/share/i18n/locales/iso14651_t1_commoncontiene

 <U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .

Eliminé esta línea, corrí sudo locale-geny reinicié mi computadora. Lamentablemente, esto no cambió nada.

Gavilán
fuente

Respuestas:

11

OP estuvo muy cerca de la edición /usr/share/i18n/locales/iso14651_t1_common, pero el truco es no eliminar la línea

<U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .

sino más bien modificarlo a

<U002E> <RES-1>;IGNORE;IGNORE;<U002E> # 47 .

Por que esto funciona

Las IGNOREdeclaraciones especifican que el punto final (también conocido como punto o carácter <U002E>) se ignorará al ordenar palabras alfabéticamente. Para que sus archivos de puntos sean lo primero, cambie IGNOREa un símbolo de clasificación que aparezca antes que todos los demás caracteres. Los símbolos de clasificación se definen mediante líneas como

collating-symbol <something-inside-angle-brackets>

y están ordenados por la apariencia de la línea

<something-inside-angle-brackets>

En mi copia de iso14651_t1_common, el primer símbolo de clasificación es <RES-1>, que aparece en la línea 3458. Si el archivo es diferente, use el símbolo de clasificación que se ordene primero.

Detalles sobre el pedido de caracteres con LC_COLLATE

<U002E>tiene tres IGNOREdeclaraciones porque las letras se pueden comparar varias veces en caso de empate. Para entender esto, considere minúsculas ay mayúsculas A(que son parte de un grupo de caracteres que realmente se comparan cuatro veces):

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

Tener múltiples rondas de comparación permite que los archivos que comienzan con "a" y "A" se agrupen porque ambos se comparan como <a>en la primera pasada, y la siguiente letra determina el orden. Si todas las siguientes letras son iguales (por ejemplo, a.txty A.txt), la tercera pasada se colocará a.txtprimero porque el símbolo de clasificación para letras minúsculas <MIN>aparece en la línea 3467, antes del símbolo de clasificación para letras mayúsculas <CAP>(línea 3488).

Implementando este cambio

Si desea que el período sea el primero cada vez que un programa ordena usar cartas LC_COLLATE, puede modificarlo iso14651_t1_commoncomo se describió anteriormente y reconstruir su archivo de ubicaciones. Pero si desea realizar este cambio solo en lsy sin acceso a la raíz, puede copiar los archivos locales originales a otro directorio antes de modificarlos.

Lo que hice

Mi localidad por defecto es en_US, por lo copié en_US, iso14651_t1y iso14651_t1_commona $HOME/path/to/new/locales. Allí realicé el cambio mencionado anteriormente iso14651_t1_commony cambié el nombre en_USa en_DOTFILE. Luego compilé el entorno local en_DOTFILE con

localedef -i en_DOTFILE -f UTF-8 -vc $HOME/path/to/new/locales/en_DOTFILE.UTF-8

Para reemplazar el lsorden predeterminado , cree un script BASH llamado ls:

#!/bin/bash
LOCPATH=$HOME/path/to/new/locales LANG=en_DOTFILE.UTF-8 ls "$@"

guárdelo en algún lugar que aparezca antes /usr/binen su ruta y hágalo ejecutable con chmod +x ls.

beandip
fuente
por supuesto, tendrá que agregar -a o -A para ver sus archivos de puntos, pero a menos que siempre quiera verlos, tiene sentido hacerlo en la línea de comandos, no en su script BASH
beandip
¡Brillante! Gracias, esto es perfecto! Acabo de modificar el archivo propiedad de la raíz, por lo que no probé su script. Sin embargo, creo que necesitas poner comillas dobles alrededor de tu $@.
Sparhawk
buena llamada - comillas dobles agregadas
beandip
11

Se puede utilizar un orden de publicación de la cáscara en su lugar (que puede no implicar orden de clasificación de la configuración regional; bash, AT & T ksh, yash, tcshy zshdar los resultados esperados, mkshy dash. No lo fishparece dar una orden de mayúsculas y minúsculas, pero da resultados diferentes cuando hay no ASCII caracteres):

ls -dUl -- .* *

Esto proporciona lsuna lista explícita de archivos (y directorios) para enumerar, y desactiva lsla ordenación ( -Uque es una extensión de GNU).

Hay algunas advertencias, dependiendo del caparazón que estés usando.

  • Con zsh, la nomatchopción predeterminada hará que el comando falle si el directorio no contiene archivos ocultos y no ocultos; podría deshabilitarlo nomatchpara evitar eso, pero sería mejor hacerlo en su set -o cshnullgloblugar (y el comando fallará solo si ninguno de los globos coincide con (t)cshlos shells de Unix anteriores o anteriores).
  • Con zsh, pdkshy su derivada y fish, .*la expansión de, no incluye .y .., así que esto coincide ls -Al. Con otros proyectiles .y ..están incluidos para que coincida ls -al. En el último caso, necesitaría cambiar los patrones globales para excluir .y ..( ls -dUl -- ..?* .[!.]* *).
  • Excepto en fish, (t)csho zsh, si alguno de los patrones globales no coincide con nada, lsproducirá un mensaje de error; puede evitar esto ya sea configurando la nullglobopción (en basho zshal menos), o redirigiendo stderra /dev/null( ls -dUl -- ..?* .[!.]* * 2>/dev/null). Si lo usa nullglob, tenga cuidado con el comportamiento potencialmente sorprendente que causa (vea Shell comiendo caracteres `?` ). fishse comporta como bashcon, nomatchexcepto que cuando es interactivo, se emitirá un mensaje de advertencia para cada globo que no tiene coincidencia.

(¡Gracias a Stéphane Chazelas por todos los comentarios!)

Stephen Kitt
fuente
Tenga en cuenta que no todos los shells ordenarán la lista utilizando el orden de clasificación del entorno local. mkshy, dashpor ejemplo, no clasificará entre mayúsculas y minúsculas.
Stéphane Chazelas
1
Tenga en cuenta que -U(es decir, sin clasificar) es una extensión GNU. Algunas otras lsimplementaciones como FreeBSD tienen un -Upero no es para una lista sin clasificar.
Stéphane Chazelas
Con GNU ls, necesita --antes .*ya que esa implementación acepta opciones después de argumentos (a menos que POSIXLY_CORRECT esté en el entorno)
Stéphane Chazelas
Disimulado (+1)! Sin embargo, no estoy seguro de cómo usaría esto fácilmente en todos los casos, es decir, en un alias o función. Por ejemplo, tendría que cambiar si quiero especificar un directorio específico lscomo argumento.
Sparhawk
1
@PeterCordes [!.]es correcto. Ver pubs.opengroup.org/onlinepubs/9699919799/utilities/… . Algunos (¿la mayoría?) Shells permiten ^como sinónimo de !globos de clase de caracteres negados. En cualquier caso, prefiero .[!.] .??* *que sea un poco más comprensible que.[!.]* ..?* *
jrw32982 es compatible con Monica el
4

Simplemente puede usar dos lscomandos separados :

$ ls -dl ..?* .[^.]* 2>/dev/null ; ls -dl *
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 .a
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 .b
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 a
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 A
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 b
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 B
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 你好嗎

A diferencia de las otras respuestas hasta ahora, este enfoque muestra los archivos de puntos primero evitando las entradas .y .., luego las entradas restantes en ls orden alfabético.

Las respuestas de @StephenKitt podrían mejorarse para lograr el mismo resultado:

$ ls -dUl ..?* .[^.]* * 2>/dev/null
jlliagre
fuente
+1 también, pero según la respuesta de StephenKitt, no estoy seguro de cómo usaría esto fácilmente en todos los casos, es decir, en un alias o función. Por ejemplo, tendría que cambiar si quiero especificar un directorio específico lscomo argumento. (FWIW estoy usando zsh, pero esto es útil para bash-people, supongo).
Sparhawk
-2

Puedes jugar con las opciones de comando ls . Prueba esto:

# ls -laXr

Dónde:

-l     use a long listing format
-a, --all
              do not ignore entries starting with .
-X     sort alphabetically by entry extension
-r, --reverse
              reverse order while sorting
Rodrigo Calvo
fuente
Lo siento, eso no parece hacer lo que quiero. La -Xbandera se ordena por la extensión después de ., que es totalmente diferente. Además, los archivos están en orden alfabético inverso. Además, aunque los archivos de puntos son los primeros para mi ejemplo, no funcionará en todos los casos (por ejemplo a.b c.d .a .c). Además, has usado en -alugar de -A.
Sparhawk