Tengo un directorio lleno de archivos con nombres como logXX
donde XX es un número hexadecimal en mayúscula de dos caracteres, con relleno de cero, como:
log00
log01
log02
...
log0A
log0B
log0C
...
log4E
log4F
log50
...
En general, habrá menos de 20 o 30 archivos en total. La fecha y hora en mi sistema en particular no es algo en lo que se pueda confiar (un sistema integrado sin fuentes de tiempo confiables NTP o GPS). Sin embargo, los nombres de los archivos se incrementarán de manera confiable como se muestra arriba.
Deseo revisar grep
todos los archivos para la entrada de registro más reciente de un tipo determinado, esperaba cat
reunir los archivos juntos, como ...
cat /tmp/logs/log* | grep 'WARNING 07 -' | tail -n1
Sin embargo, se me ocurrió que diferentes versiones de bash
or sh
o zsh
etc. podrían tener diferentes ideas sobre cómo *
se expande.
La man bash
página no dice si la expansión de *
sería una lista alfabética definitivamente ascendente de nombres de archivos coincidentes. Parece estar ascendiendo cada vez que lo he probado en todos los sistemas que tengo disponibles, pero ¿es un comportamiento DEFINIDO o solo una implementación específica?
En otras palabras, ¿puedo confiar absolutamente en cat /tmp/logs/log*
concatenar todos mis archivos de registro juntos en orden alfabético?
sort
es el mismo que para el shell cuando se expande un patrón global de nombre de archivo.cat
congrep -h pattern /tmp/logs/log*
para suprimir los nombres de archivo anteriores a las coincidencias. (Al menos con GNU grep, no verifiqué POSIX o busybox.)cat
, este es un uso inútil delsort
Respuestas:
En todos los depósitos, los globos se ordenan por defecto. Ya fueron ayudados por el
/etc/glob
ayudante llamado por el caparazón de Ken Thompson para expandir los globos en la primera versión de Unix a principios de los años 70 (y que dieron su nombre a los globos).Para
sh
, POSIX requiere que se ordenen porstrcoll()
, es decir, utilizando el orden de clasificación en la configuración regional del usuario, comols
aunque algunos todavía lo hacen a través destrcmp()
, que se basa solo en valores de bytes.Puede observar más arriba que para aquellos shells que hacen la clasificación basada en la configuración regional, aquí en un sistema GNU con una
en_GB.UTF-8
configuración regional, los-
nombres en los archivos se ignoran para la clasificación (la mayoría de los caracteres de puntuación lo harían). Eló
se clasifica de una manera más esperada (al menos para los británicos), y el caso se ignora (excepto cuando se trata de decidir los lazos).Sin embargo, notará algunas inconsistencias para log① log②. Esto se debe a que el orden de clasificación de ① y ② no está definido en las configuraciones regionales de GNU (actualmente; con suerte, se solucionará algún día). Clasifican lo mismo, por lo que obtienes resultados aleatorios.
Cambiar la configuración regional afectará el orden de clasificación. Puede establecer la configuración regional en C para obtener un
strcmp()
tipo similar:Tenga en cuenta que algunas configuraciones regionales pueden causar algunas confusiones incluso para las cadenas all-alnum all-ASCII. Al igual que los checos (al menos en los sistemas GNU), ¿dónde
ch
hay un elemento de clasificación que se ordena después deh
:O, como señaló @ninjalj, incluso los más extraños en los locales húngaros:
En
zsh
, puede elegir la clasificación con calificadores globales . Por ejemplo:El tipo numérico
echo *(n)
también se puede habilitar globalmente con lanumericglobsort
opción:Si usted (como yo estaba) está confundido por ese orden en ese caso particular (aquí usando mi configuración regional británica), vea aquí para más detalles.
fuente
&C<cs<<<Cs<<<CS
, mientras&C<cs<<<cS<<<Cs<<<CS
está marcado como un borrador experimental propuesto. A juzgar por algunos datos más antiguos importados a CLDR, los AIX y MS más antiguos parecían preferir la vista "minúsculas y luego mayúsculas son 2 elementos de clasificación diferentes".La página del manual para bash especifica:
fuente
man
en la representación de texto ... si el texto que estoy buscando se "ajusta", entonces un comando / search no lo encontrará. Simplemente maximicé mi terminal y ahí está :)bash
. Tho OP también estaba interesado en "zsh, etc."A menos que active algunas opciones de shell muy específicas en algunos shells, se garantiza que la salida sea la misma.
El orden se especifica en el estándar POSIX :
Vea también la categoría LC_COLLATE en POSIX Locale , que en resumen dice que si
LC_COLLATE=C
, entonces las cosas se ordenan en orden ASCII.El
bash
manual mencionaksh93
yzsh
tiene una redacción similar, lo que me lleva a creer que siguen el estándar POSIX a este respecto.Otros shells, como
pdksh
ydash
no dicen nada sobre la clasificación de los nombres de archivo resultantes de la globalización de nombres de archivo. Estoy tentado a creer que esto significa que todavía se adhieren al mismo estándar, al menos cuando se usa la ubicación POSIX. En mi experiencia, no he encontrado un shell que haga una clasificación abiertamente "extraña" de los nombres de archivo ASCII.fuente
numericglobsort
opciónzsh
que afectaría la clasificación. Aunque prefiero habilitarlo en función de cada globo, en lugarecho *(n)
de activar la opción globalmente.--posix
opción de línea de comando o ejecutarset -o posix
posix
modo de Bash no afecta la ordenación de la expansión de los caracteres globales de nombre de archivo . Consulte gnu.org/software/bash/manual/html_node/Bash-POSIX-Mode.html. Esto me lleva a creer (espero, más bien) que la clasificación es compatible con POSIX.Si el objetivo principal es ordenar los archivos de entrada por edad, primero los más antiguos, puede escribir
Y si los registros rotados y comprimidos también están involucrados:
fuente