renomeia arquivos em lote

6

Durante a importação de arquivos de música do backup (graças ao esquema de nomenclatura padrão de rhythmbox ), atrapalhei os nomes dos arquivos. Agora a aparência é:

00 - American Pie.ogg.ogg.ogg.ogg
00 - American Pie.ogg.ogg.ogg.ogg.ogg
00 - another brick in the wall.ogg.ogg.ogg.ogg
00 - another brick in the wall.ogg.ogg.ogg.ogg.ogg
00 - candle_in_the_wind.ogg.ogg.ogg.ogg
00 - candle_in_the_wind.ogg.ogg.ogg.ogg.ogg

Enquanto o arquivo deve se parecer com

American Pie.ogg
another brick in the wall.ogg
candle_in_the_wind.ogg

E eu tenho (a partir de wc -l ) 3096 desses arquivos. Como posso restaurá-lo no modo batch? Eu tentei usar o rename e o mmv , como mostrado no pergunta, mas não está funcionando (problema com a sintaxe rename e, para mmv , há colisão).

Alguma ajuda, por favor?

    
por BaRud 23.01.2014 / 20:21

5 respostas

7

Usando perl-rename (que é uma das duas ferramentas mais comumente chamada rename ; a outra usa uma sintaxe muito diferente e não pode fazer isso em uma etapa):

rename -f 's/00 - ([^.]*).*/$1.ogg/' *.ogg

A opção -f ou --force faz renomear os arquivos existentes.

A segunda parte é uma substituição de expressão regular em estilo perl. A sintaxe básica é s/replacethis/withthis/ O padrão para corresponder - 00 - ([^.]*).* - corresponderá a todos os arquivos * .ogg com nomes como os da sua pergunta. 00 - - obviamente, isso apenas corresponde ao padrão no início de cada um dos nomes de arquivos. ([^.]*) é a carne da expressão regular. [^.] corresponderá a qualquer caractere único que não seja . , enquanto * significa 'qualquer número da coisa anterior', então [^.]* significa 'qualquer número de caracteres que não são . ' . Os parênteses marcam um grupo de captura (mais sobre isso em um segundo). Em expressões regulares, . significa 'qualquer caractere' (se você quiser um ponto literal neste lado da substituição você tem que escapar, como em: \. ), então o% final .* significa 'qualquer número de qualquer personagem '.

Na segunda parte do comando de substituição, $1 significa 'o primeiro grupo de captura' - isto é, aquele que está contido dentro do primeiro par de parênteses (veja? Disse a você que eu voltaria a ele) . O .ogg significa um literal '.ogg' - neste lado da substituição, você não precisa escapar do ponto.

Então, aproximadamente traduzido para o inglês, 's/00 - ([^.]*).*/$1.ogg/' está dizendo rename para "tirar" 00 - ", seguido por (qualquer número de caracteres que não sejam um ponto), então qualquer número de caracteres; e substitua-o pelos caracteres contidos nos colchetes e ".ogg." '.

Em alguns sistemas, renomear perl é chamado prename (quando rename é obtido pelo outro programa mencionado anteriormente). Em alguns sistemas, não está disponível: (

Para recursividade, você pode fazer o seguinte:

shopt -s globstar ## assuming your shell is bash
rename 's/00 - ([^.]*).*/$1.ogg/' **/*.ogg

Ou:

find . -name '*.ogg' -exec rename 's/00 - ([^.]*).*/$1.ogg/' {} +
    
por 23.01.2014 / 20:52
4

Isso deve funcionar:

$ for f in *ogg; do 
   mv "$f" "$(printf "%s" "$f" | perl -lpe 's/^\d+ - (.*?).ogg.*/$1.ogg/')";
 done

Para fazer isso para todos os arquivos, incluindo aqueles em subdiretórios, ative globstar se você estiver usando o bash:

$ shopt -s globstar
$ for f in **/*ogg; do 
   mv "$f" "$(printf "%s" "$f" | perl -lpe 's/^\d+ - (.*?).ogg.*/$1.ogg/')";
 done

Explicação:

O material funky está sendo tratado pelo perl. É uma expressão regular simples que remove todos os números ( \d+ ) seguidos por - (que é um traço com espaço em ambos os lados) desde o início da cadeia de entrada, combina tudo até o punho .ogg e substitui o envio após que com a string combinada ( $1 ) e .ogg .

Isso pode ser expandido para o mais complicado, mas mais legível:

for f in *ogg; do 
   newname=$(printf "%s" "$f" | perl -lpe 's/^\d+ - (.*?).ogg.*/$1.ogg/')";
   mv "$f" "$newname";
 done
    
por 23.01.2014 / 20:41
3

Um shell compatível com Bourne pode fazer isso sem Perl ou sed (mas seu apelo estético é questionável ...)

for f in *.ogg
do
    newfile="${f#00 - }"          ## Strip the leading "00 - "
    newfile="${newfile%%.ogg*}"   ## Strip .ogg and everything after
    newfile="${newfile}.ogg"      ## Append .ogg
    mv "$f" "$newfile"            ## Do the rename
done

Note que também é possível usar ls -1 | while read f para criar o loop, mas essa construção quebraria no caso de encontrar um nome de arquivo com um caractere de nova linha. Usar o comportamento de globalização padrão do shell protege contra esse problema.

    
por 23.01.2014 / 23:01
1

É aí que o Midnight Commander vem à mão. Selecione os arquivos com "+" ou "Inserir". Pressione F6 para renomear. Defina a máscara como *.ogg.ogg.ogg e o destino como * e pressione Enter. Claro, não é automatizado, mas ainda está "em lote".

    
por 23.01.2014 / 22:49
0
ls -1|while read f; do 
    newfile=$(echo $f|sed -e 's/\(\.ogg\)*$/.ogg/')
    mv "$f" "$newfile"
  done
    
por 23.01.2014 / 20:28

Tags