Eu tenho um diretório preenchido com arquivos com nomes como logXX
onde XX é um número hexadecimal de dois caracteres, preenchido com zero e maiúsculo, como:
log00
log01
log02
...
log0A
log0B
log0C
...
log4E
log4F
log50
...
Geralmente, haverá menos do que 20 ou 30 arquivos no total. A data e a hora no meu sistema em particular não são confiáveis (um sistema incorporado sem fontes confiáveis de hora NTP ou GPS). No entanto, os nomes dos arquivos serão incrementados de forma confiável, como mostrado acima.
Desejo grep
examinar todos os arquivos da entrada de registro mais recente de um determinado tipo, esperando que cat
os arquivos juntos, como ...
cat /tmp/logs/log* | grep 'WARNING 07 -' | tail -n1
No entanto, ocorreu-me que versões diferentes de bash
ou sh
ou zsh
etc. podem ter idéias diferentes sobre como a *
expansão é expandida.
A man bash
página não diz se a expansão *
seria ou não uma lista alfabética definitivamente crescente de nomes de arquivos correspondentes. Parece estar aumentando cada vez que tentei em todos os sistemas que tenho disponíveis - mas é um comportamento DEFINIDO ou apenas uma implementação específica?
Em outras palavras, posso confiar absolutamente cat /tmp/logs/log*
para concatenar todos os meus arquivos de log em ordem alfabética?
sort
é a mesma da shell quando está expandindo um padrão de globbing de nome de arquivo.cat
comgrep -h pattern /tmp/logs/log*
suprimir nomes de arquivos anexados às correspondências. (Pelo menos com GNU grep, eu não verificar POSIX ou busybox.)cat
, este é o uso inútil desort
Respostas:
Em todos os shells, os globs são classificados por padrão. Eles já foram
/etc/glob
chamados pelo assistente de Ken Thompson para expandir os globs na primeira versão do Unix no início dos anos 70 (e que deram o nome aos globs).Pois
sh
, o POSIX exige que eles sejam classificados por meio destrcoll()
, isto é, usando a ordem de classificação no código do idioma do usuário, como,ls
embora alguns ainda o façam, comstrcmp()
base apenas em valores de bytes.Você pode observar acima que, para os shells que fazem a classificação com base na localidade, aqui em um sistema GNU com uma
en_GB.UTF-8
localidade, os-
nomes dos arquivos são ignorados na classificação (a maioria dos caracteres de pontuação o faria). Aó
classificação é ordenada de maneira mais esperada (pelo menos para o povo britânico), e o caso é ignorado (exceto quando se trata de decidir laços).No entanto, você notará algumas inconsistências no log① log②. Isso ocorre porque a ordem de classificação de ① e ② não está definida nos locais GNU (atualmente; esperamos que seja corrigido algum dia). Eles têm a mesma classificação, para que você obtenha resultados aleatórios.
Alterar a localidade afetará a ordem de classificação. Você pode definir o código do idioma para C para obter uma
strcmp()
classificação semelhante a:Observe que alguns códigos de idioma podem causar algumas confusões, mesmo para cadeias all-alnum all-ASCII. Como os tchecos (pelo menos nos sistemas GNU),
ch
é um elemento de classificação que se classifica depoish
:Ou, como apontado por @ninjalj, ainda mais estranhos nos locais húngaros:
Em
zsh
, você pode escolher a classificação com qualificadores glob . Por exemplo:A ordenação numérica
echo *(n)
também pode ser ativada globalmente com anumericglobsort
opção:Se você (como eu estava) está confuso com essa ordem nessa instância específica (aqui usando meu local britânico), consulte aqui para obter detalhes.
fonte
&C<cs<<<Cs<<<CS
, while&C<cs<<<cS<<<Cs<<<CS
é marcado como um rascunho experimental proposto. A julgar por alguns dados mais antigos importados para o CLDR, o AIX e o MS mais antigos pareciam preferir a visualização "minúsculas e maiúsculas de dois elementos de agrupamento diferentes".A página de manual do bash especifica:
fonte
man
renderização de texto ou de massa de vidraceiro ... se o texto que estou procurando for "digitado", o comando / search não o encontrará. Apenas maximizei meu terminal e aí está :) #bash
. Tho OP também estava interessado em "zsh etc."A menos que você ative algumas opções de shell muito específicas em alguns shells, é garantido que a saída seja a mesma.
A ordem é especificada no padrão POSIX :
Consulte também LC_COLLATE Category no código do idioma POSIX , que em resumo diz que se
LC_COLLATE=C
, então, as coisas são ordenadas em ordem ASCII.O
bash
manual mencionaksh93
ezsh
possui uma formulação semelhante, o que me leva a acreditar que eles seguem o padrão POSIX a esse respeito.Outros shells, como
pdksh
edash
não dizem nada sobre a classificação dos nomes de arquivos resultantes do globbing do nome do arquivo. Fico tentado a acreditar que isso significa que eles ainda seguem o mesmo padrão, pelo menos ao usar o código do idioma POSIX. Na minha experiência, não encontrei um shell que faça uma classificação abertamente "estranha" de nomes de arquivos ASCII.fonte
numericglobsort
opçãozsh
que afetaria a classificação. Embora eu prefira ativá-lo em uma base por glob doecho *(n)
que ativar a opção globalmente.--posix
opção de linha de comando ou executarset -o posix
posix
modo Bash . Veja gnu.org/software/bash/manual/html_node/Bash-POSIX-Mode.html Isso me leva a acreditar (espero) que a classificação é compatível com POSIX.Se o objetivo principal é classificar os arquivos de entrada por idade, mais antigos primeiro, você pode escrever
E se os logs rotacionados e compactados também estiverem envolvidos:
fonte