classificação estranha de nome de arquivo (bash, ls, sort)

2

Bom dia a todos.

Estou tentando alimentar minha música para o mplayer, assim: mplayer * , mas recebendo a ordem errada das faixas.

Aqui está o que eu recebo com ls (assim como ls -1 , ls -1 | sort ), anote a ordem dos números 'I', 'II', 'III' dentro dos concertos:

Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: II.Largo e Spiccato.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: I. Adagio e spiccato.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: II.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: III.Larghetto.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: IV. Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: II.Largo.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: I.Adagio.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: II.Allegro assai.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: II.Largo.mp3

Parece que a classificação é feita por algo como o nome da faixa em vez do número da faixa, como eu diria ao bash para classificar os arquivos lexicograficamente?

Aqui estão mais algumas informações que podem ser relevantes:

$ LC_ALL=C type ls
ls is aliased to 'ls --color=auto'
$ locale
LANG=ru_RU.UTF-8
LANGUAGE=
LC_CTYPE="ru_RU.UTF-8"
LC_NUMERIC="ru_RU.UTF-8"
LC_TIME="ru_RU.UTF-8"
LC_COLLATE="ru_RU.UTF-8"
LC_MONETARY="ru_RU.UTF-8"
LC_MESSAGES="ru_RU.UTF-8"
LC_PAPER="ru_RU.UTF-8"
LC_NAME="ru_RU.UTF-8"
LC_ADDRESS="ru_RU.UTF-8"
LC_TELEPHONE="ru_RU.UTF-8"
LC_MEASUREMENT="ru_RU.UTF-8"
LC_IDENTIFICATION="ru_RU.UTF-8"
LC_ALL=
$ LC_ALL=C bash --version
GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)
$ LC_ALL=C ls --version
ls (GNU coreutils) 8.13
Copyright (C) 2011 Free Software Foundation, Inc.

upd. Eu armazenei dois primeiros nomes de arquivos em arquivos:

$ ls -1 | head -n1 > fname1; ls -1 | head -n2 | tail -n1 > fname2

em seguida, examinou esses dois arquivos com meld ( diff GUI) para garantir que não haja caracteres, como espaços não quebráveis, que possam interferir na classificação. Então… não existem tais personagens, não há diferença exceto para o claramente visível. O mesmo para o segundo e o terceiro nome de arquivo.

    
por gluk47 29.04.2013 / 14:15

3 respostas

2

Você pode definir sua localidade temporariamente pela duração de um comando: Eu coloco sua lista de arquivos em um arquivo chamado files :

O que você vê:

$ LC_ALL='ru_RU.UTF-8' sort files
Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: II.Largo e Spiccato.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: I. Adagio e spiccato.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: II.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: III.Larghetto.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: IV. Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: II.Largo.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: I.Adagio.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: II.Allegro assai.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: II.Largo.mp3

Ordenado como você deseja:

$ LC_ALL=C sort files
Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: II.Largo e Spiccato.mp3
Antonio Vivaldi - Op.3 concerto No.1 D-dur RV 549: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: I. Adagio e spiccato.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: II.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: III.Larghetto.mp3
Antonio Vivaldi - Op.3 concerto No.2 g-moll RV 578: IV. Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: II.Largo.mp3
Antonio Vivaldi - Op.3 concerto No.3 G-dur RV 310: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: I.Adagio.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: II.Allegro assai.mp3
Antonio Vivaldi - Op.3 concerto No.4 e-moll RV 550: III.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: I.Allegro.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: II.Largo.mp3
Antonio Vivaldi - Op.3 concerto No.5 A-dur RV 519: III.Allegro.mp3

Especificamente, você deseja definir a variável LC_COLLATE como C

    
por 29.04.2013 / 16:46
2

Como você já resolveu seu problema (pelo menos para números romanos até 8), esta é uma observação geral:

ls * não é uma boa opção para verificar a ordem dos arquivos quando eles são passados para o seu reprodutor de músicas com mplayer * . Isso porque o próprio ls pode reorganizar os arquivos - e não é garantido que o mecanismo seja o mesmo usado pelo shell. Depende das suas configurações. Use echo * - ou para uma saída mais bonita printf "%s\n" * .

Este exemplo ilustra isso com meu alias pessoal ls="ls -v" :

$ touch 1 2 3 12
$ ls *
1  2  3  12
$ echo *
1 12 2 3
$ printf "%s\n" *
1
12
2
3

Uma solução muito melhor é possível com zsh , mas AFAIK não com bash :

Mikael Magnusson postou uma função magnífica para lidar com números romanos na lista de discussão zsh. Sem entrar em detalhes da função em si, é assim que funciona:

$ touch I II III IV V VI VII VIII IX X L C D M
$ print *
C D I II III IV IX L M V VI VII VIII X
$ print *(no+romansort)
I II III IV V VI VII VIII IX X L C D M

No último comando de impressão (no+romansort) informa ao shell, que você deseja classificar numérico ( n ) e usar uma função personalizada ( o+ ) para analisar primeiro os nomes dos arquivos.

Isso, claro, funciona quando o número romano é apenas parte do nome do arquivo. Mas esteja ciente de que você precisa que a opção HIST_SUBST_PATTERN seja definida!

    
por 30.04.2013 / 13:07
1

Por algum motivo, classificar no Mac OSX (10.8.3) classifica os números romanos na ordem correta.

Não obstante, o que dizer de substituir primeiro os números romanos antes de alimentá-los para classificar:

cat filename.txt | sed 's/IV/4/g' | sed s'/III/3/g' | sed 's/II/2/g' | sed 's/I/1/g' | sort

Isso funcionou para mim (mas novamente eu tentei isso no OSX).

    
por 29.04.2013 / 15:18