Tentando fazer aritmética na ferramenta de renomeação de Perl (Debian)

8

Vamos supor que eu tenha cinco arquivos mp3:

01-trackfoo.mp3
02-trackbar.mp3
03-trackbaz.mp3
04-trackabc.mp3
05-trackxyz.mp3

Agora, ouço rapidamente os arquivos (apenas o mplayer no console fará o truque) e descubro que as faixas estão na ordem errada . 05 é realmente 02 e o restante terá que ser renomeado. Então, primeiro farei uma mudança de nome temporário:

01-trackfoo.mp3

02-trackbar.mp3
03-trackbaz.mp3
04-trackabc.mp3
00-trackxyz.mp3

Agora precisamos de um "turno": 02 deve se tornar 03, 03 deve se tornar 04 e 04 deve se tornar 05. Para minimizar a confusão, ex-05 (agora 00) será mveditado mais tarde.

Minha abordagem foi a seguinte: (perl rename, de Larry Wall, padrão aqui no Debian)

rename 's/0([2-4])([\s\S]+)/0($1+1)$2/' *

bem como (mais tarde, depois de mais alguns RTFM'ing)

rename 's/0([2-4])([\s\S]+)/0($1+1)$2/e' *

Nenhum deles trabalhou, especialmente porque o /e[val]modificador não aceita qualquer outra coisa , mas avaliações, e irá lançar um erro uma vez que você tentar combinar as avaliações com cordas. O bashpode fazer isso muito bem, por exemplo, foo$((1+6))será avaliado como foo7.

Então, como posso fazer isso (preferencial de uma linha, não pretendendo escrever um script independente inteiro apenas para isso)?

erro de sintaxe
fonte

Respostas:

7

Você quase teve. Você só precisa explicitar seqüências de caracteres literais e concatenação de seqüências na /esubstituição modificada, usando aspas e o operador de ponto.

rename 's/0([2-4])([\s\S]+)/"0".($1+1).$2/e' *
Alan Curry
fonte
Ele deixa o 05 original ainda sem renomear, mas +1 por resolver a falha de uma linha .
precisa saber é o seguinte
1
(menor nota, renomeação é chamado prename no Ubuntu) ... Se nenhum nome no diretório começa com $'\x01'2em seguida, uma renomeação preliminar assim: prename 's/^05/\x012/' 05*.., o texto acima [2-4]renomeação .. então uma final prename 's/^\x01/0/' $'\x01'2*irá fazer o truque .. Isso faz 3 um -liners ... para um quarto, e uma inicial de seleção para a possível presença de um arquivo começando com $'\x01', algo assim festa armadilha trecho vontade ele ..shopt -s nullglob; x=($'\x01'*); [[ -n $x ]] && { echo '\x01' is not suitable; exit; }
Peter.O
YEEES! Obrigado Alan, eu não pensei nesse operador de ponto, embora soubesse o que fazer em palavras legíveis por humanos: "diga para não tocar nas coisas fora de ()" :) :) E obrigado a Peter pela festança abordagem também. Além disso, se eu tivesse alguma idéia de quão próxima a sintaxe do PHP está da Perl, provavelmente teria encontrado a solução por tentativa e erro. Porque esse ponto é a contrapartida JavaScript '+' no PHP para concatenação de strings.
Syntaxerror
4

preferencial de uma linha, não pretendendo escrever um script autônomo inteiro apenas para esse

Quando as coisas ficam tão complicadas, não vejo motivo para não escrever um script. Você nunca vai se lembrar de como fazer isso de uma execução para a próxima, então você acabará reinventando a cada vez ou agrupando-o em um script de qualquer maneira.

Para uma coisa pequena como essa, geralmente começo a tentar resolvê-lo no Bash:

#!/bin/bash
if [ -z "$1" ] ; then echo Need arguments. ; exit 1 ; fi

typeset -i i=1
for f in "$*"
do
    tailbits=`echo "$f" | sed -e 's/^[0-9]+//'`
    mv "$f" sertmp-`printf %02d $i`"$tailbits"
    i=i+1
done

for f in "sertmp-*"
do
    mv "$f" `echo "$f" | sed -e s/^sertmp-//` 
done

Basicamente, esse script retira todos os dígitos iniciais e coloca um número de série crescente preenchido com zero na frente, com os arquivos numerados de acordo com a ordem em que você os passa para o script.

Isso é feito em duas etapas, com sertmp-prefixos para a primeira passagem, para evitar qualquer risco de colisão de nomes. Se você chamar esse script mp3-renamere chamar assim:

$ mp3-renamer 01-foo.mp3 03-bar.mp3 04-qux.mp3

você se depara com uma colisão trivial na primeira renomeação se não usar 2 passes para renomear. ( 01-foo.mp3-> 01-foo.mp3.)

Se você chamar assim, porém:

$ mp3-renamer 02-foo.mp3 01-foo.mp3

você acidentalmente apaga 01-foo.mp3na primeira renomeação com uma renomeação de 1 passagem.

Se o problema se complicar, eu o reescrevo no Perl. Nesse ponto, você poderia usar um hash para conter o mapeamento de nomes antigos e novos, e usar um pouco de código inteligente para descobrir a ordem correta para fazer as renomeações, a fim de evitar a necessidade de 2 passagens.

Warren Young
fonte