No bash, como ordenar strings com números nelas?

33

Se eu tiver esses arquivos em um diretório

cwcch10.pdf
cwcch11.pdf
cwcch12.pdf
cwcch13.pdf
cwcch14.pdf
cwcch15.pdf
cwcch16.pdf
cwcch17.pdf
cwcch18.pdf
cwcch1.pdf
cwcch2.pdf
cwcch3.pdf
cwcch4.pdf
cwcch5.pdf
cwcch6.pdf
cwcch7.pdf
cwcch8.pdf
cwcch9.pdf

como posso listá-los no Bash para que eles fiquem em ordem numérica crescente com base na parte numérica da string. Então, o pedido resultante é cwcch1.pdf, cwcch2.pdf, ..., cwcch9.pdf, cwcch10.pdf , etc.

O que estou tentando fazer é concatenar os pdfs com pdftk com algo como o seguinte

pdftk 'ls *.pdf | sort -n' cat output output.pdf

mas isso não funciona porque a minha classificação está errada.

    
por ngm 06.12.2009 / 01:14

7 respostas

6

Algo parecido com isso pode fazer o que você quer, mas é preciso uma abordagem um pouco diferente:

pdftk $(for n in {1..18}; do echo cwcch$n.pdf; done) cat output output.pdf
    
por 06.12.2009 / 01:25
46

Seu sort pode ter a capacidade de fazer isso para você:

sort --version-sort
    
por 06.12.2009 / 04:05
30

Para este exemplo específico, você também pode fazer isso:

ls *.pdf | sort -k2 -th -n

Isto é, digite numericamente (-n) no segundo campo (-k2) usando 'h' como o separador de campo (-th).

    
por 06.12.2009 / 03:10
5

Você pode usar a opção -v no GNU ls : tipo natural de números (versão) no texto.

ls -1v cwcch*

Isso não funciona com o BSD ls (por exemplo, no OS X), em que a opção -v tem um significado diferente.

    
por 20.08.2013 / 06:43
2

Use a expansão shell diretamente em uma linha de comando. A expansão deve encomendá-los corretamente. Se eu entendi a sintaxe da linha de comando de pdftk corretamente, isso fará o que você quer:

# shell expansion with square brackets
pdftk cwcch[1-9].pdf cwcch1[0-9].pdf cat output output.pdf

# shell expansion with curly braces
pdftk cwcch{{1..9},{10..18}}.pdf cat output output.pdf

Ou você pode tentar uma abordagem diferente. Quando eu preciso fazer algo assim, eu costumo tentar obter meus números formatados corretamente antes do tempo. Se eu estou chegando tarde e os PDFs já estão numerados como o seu exemplo, eu vou usar isso para renumerar:

# rename is rename.pl aka prename -- perl rename script
# this adds a leading zero to single-digit numbers
rename 's/(\d)/0$1/' cwcch[1-9].pdf

Agora, a classificação padrão de ls funcionará corretamente.

    
por 06.12.2009 / 04:36
2

Aqui está um método usando apenas ordenação:

ls | sort -k1.6n
    
por 15.10.2014 / 07:51
0

Classificar -g é usado para classificar números em ordem crescente.

anthony@mtt3:~$ sort --help | egrep "\-g"
-g, --general-numeric-sort  compare according to general numerical value


O seguinte forro interage sobre um arquivo com os nomes dos arquivos PDF e pega os números apenas com egrep -o e usa sort -g para ordenar os números em ordem crescente . Em seguida, ele alimenta esses números para sed e os conecta. Em seguida, limita a saída de duplicatas com uniq.


No lugar do uniq, você também pode usar o awk:

awk '!x[$0]++'

O acima é equivalente a uniq.


O que você procura é este one liner:

for i in 'cat tmp | egrep -o "[0-9]*" | sort -g'; do cat tmp | sed "s/\(^[a-z]*\)\([0-9]*\)\(\.pdf\)/$i/g" | uniq; done


Conteúdo do tmp:

anthony@mtt3:~$ cat tmp
cwcch10.pdf
cwcch11.pdf
cwcch12.pdf
cwcch13.pdf
cwcch14.pdf
cwcch15.pdf
cwcch16.pdf
cwcch17.pdf
cwcch18.pdf
cwcch1.pdf
cwcch2.pdf
cwcch3.pdf
cwcch4.pdf
cwcch5.pdf
cwcch6.pdf
cwcch7.pdf
cwcch8.pdf
cwcch9.pdf 

EDITAR:

Saída do comando:

anthony@mtt3:~$ for i in 'cat tmp | egrep -o "[0-9]*" | sort -g'; do cat tmp | sed "s/\(^[a-z]*\)\([0-9]*\)\(\.pdf\)/$i/g" | uniq; done

cwcch1.pdf
cwcch2.pdf
cwcch3.pdf
cwcch4.pdf
cwcch5.pdf
cwcch6.pdf
cwcch7.pdf
cwcch8.pdf
cwcch9.pdf
cwcch10.pdf
cwcch11.pdf
cwcch12.pdf
cwcch13.pdf
cwcch14.pdf
cwcch15.pdf
cwcch16.pdf
cwcch17.pdf
cwcch18.pdf
    
por 30.11.2015 / 17:25