Listar arquivos classificados numericamente


123

Eu tenho um monte de arquivos de log1para log164.

Estou tentando listar o diretório (classificado) em um terminal UNIX, mas as funções de classificação estão apenas fornecendo o formato como este:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

O que eu quero é

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

Alguma sugestão sobre o que eu poderia usar para fazer isso?


8
Esta é absolutamente uma questão de programação e não merece ser migrada apenas porque a resposta envolve a linguagem de programação humilde !!!
— tchrist

Se você sabe de antemão que eles estão nomeados log1.gzatravés log164.gz, então o que você precisa mesmo de ls -1-los para?
— Ruakh 9/12

1
@ruakh ls -1 exibe os resultados em uma coluna em vez de em todo

3
@ Rabiani: Eu sei o que ls -1faz: lista nomes de arquivos. Como você já conhecia os nomes dos arquivos, não entendi para o que você precisava. Mas desde que você aceitou a resposta de Kevin, agora eu sei: você não precisava dela. O que faz mais sentido. :-)
— ruakh

Respostas:


40

bash's chaves,, {}irá enumerá-los em ordem:

for file in log{1..164}.gz; do
    process "$file"
done

267

Por que não usar o lsrecurso interno para esse caso em particular,

-v natural sort of (version) numbers within text

Por exemplo ls -1v log*


Solução impressionante, embora eu gostaria que houvesse uma solução igualmente simples, utilizando sort, no caso de um tem uma matriz de strings em vez de um diretório de arquivos
— Hubro

23
No BSD / OSX esta opção é outra coisa: -v - Force unedited printing of non-graphic characters.
— kenorb

Infelizmente, a opção -v não está disponível no AIX (6.1)
— bouvierr

6
Essa deve ser a melhor resposta.
— 32r34wgf3e

1
para MacOS isso vai funcionar, não poderia encontrar uma opção como mencionado, únicals | sort -n
— Ricky Levi

47

Com o GNU ls (ou seja, no Linux, Cygwin ou outros sistemas que possuem o GNU ls especificamente instalado):

ls -v

No zsh:

echo *(n)

Em outras conchas:

echo log?.gz log??.gz log???.gz

Substitua echopor printf '%s\n'se desejar que cada nome de arquivo esteja em uma linha separada.

Se você também deseja metadados de arquivo ( ls -l) e não possui GNU ls, precisará chamar lsseparadamente cada nome de arquivo ou grupo de nomes de arquivo que deseja ver em ordem lexicográfica.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

Para evitar essas dificuldades, use zeros à esquerda suficientes em seus nomes de arquivo para que a classificação lexicográfica seja amigável para humanos ( log001.gz, etc).


29

Embora a solução ls -1vseja certamente a melhor neste caso em particular, acho bom ter também uma que funcione sortcomo na pergunta original, pois isso funciona também quando a sua entrada não vem ls. Nesse caso, você pode usar:

ls -1 | sort -n -k1.4

A -nopção informa a classificação para classificar numericamente e -k 1.4define a chave de classificação para o primeiro campo (que é o nome do arquivo inteiro nesse caso), começando do 4º caractere até o último.


No meu caso, ls -1 | sort -n -k1.4não funciona. Dá os não ordenados no início até 4 caracteres, depois os ordenados após o 4º caractere. Eu usei em ls -1 |sort | sort -n -k1.4vez disso e funcionou perfeitamente.
— Prabhu

3
@ Prabhu, em vez disso, você poderia fazer sort -k1.1,1.3 -k1.4n. sortas implementações não precisam ser estáveis, portanto sua abordagem não funcionará com todas as implementações. Veja também a -Vopção do GNU e FreeBSD sort.
— Stéphane Chazelas

21

O GNU sort(como disponível no Linux) possui um modo de "classificação da versão" que interpreta números dentro de não-números da maneira que você solicita:

De man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Criando arquivos de teste vazios para listar
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz:)

Seu exemplo de caso, adicionando a -Vopção (ou --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz


3

Minha versão do Solaris não suporta ls -v(grrr). E a solução de classificação fornecida acima 1) requer conhecimento da posição dos dígitos no nome do arquivo e 2) não trata de coisas como números de versão com várias partes.

A abordagem abaixo é compatível com Solaris, não requer conhecimento prévio das posições dos dígitos e lida com os números de versão com 2, 3 ou 4 componentes (como: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). Ele também usa sort -fpara dobrar maiúsculas e minúsculas e manipula adequadamente diretórios misturados com arquivos:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Observe que esta versão limita o primeiro componente a um único dígito.

Se o seu sistema operacional de destino é compatível ls -v, essa é claramente a solução superior.


1

Solução Perl:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'

1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz

1
O -t .é supérfluo aqui.
— Stéphane Chazelas

0

Isso funcionou para mim.

Eu tenho arquivos 1.jpg 2.jpg ... 18.jpg

$ echo *.jpg | tr -s ' ' '\n' | sort -n

sortestá ficando confuso com a lssaída devido a caracteres coloridos não imprimíveis. Se você tentar isso:

ls -1 --color=none *.jpg | sort -n

funcionará perfeitamente.

sortpode ignorar caracteres não imprimíveis com a -iopção, mas ainda não funciona e não sei por quê.

Mas você sempre pode tirar a cor dessa maneira e sortfuncionará:

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

Espero que um dia sorttenha uma opção para isso.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.