Renomear e limpar nomes de arquivos de programas de TV como S01E01.mp4 etc.

3

Se eu tiver alguns programas de TV com nomes incorretos e precisar limpá-los

$ ls
Some_Series.1_Episode.1.mp4  'Some Series01.Episode02.mp4' SomeSeries1Episode03.mp4

Eu preciso renomear o lote para se tornarem

$ ls
S01E01.mp4  S01E02.mp4  S01E03.mp4

Eu usei o seguinte script e funciona, mas apenas quando os nomes de arquivo originais contêm números de série e de episódio 01 02 03 e não 1 2 3

#!/bin/bash
# rename tv show filenames to be kodi friendly
cd /mnt/2tb_hd/con/
if [ $? == 1 ]; then 
    exit
fi
for filename in *; do
        if [[ "$filename" =~(\**).*(.*[0-9][0-9]).*([0-9][0-9]).*(\....)$ ]]; then
            result=$(echo mv \"$filename\" S${BASH_REMATCH[2]}E${BASH_REMATCH[3]}${BASH_REMATCH[4]}\") 

                if [[ $? == 0 ]] ; then 
                    mv "$filename" "S${BASH_REMATCH[2]}E${BASH_REMATCH[3]}${BASH_REMATCH[4]}"
                fi
            fi
        done
        exit

Eu preciso fazer este código ou alterar qualquer 1 2 3 4 5 etc nos nomes dos arquivos para ter um padding 0 antes de executar o segundo loop de renomeação ou apenas alterar o código que eu já tenho que mudar 01 ou 1, independentemente do 0 preenchimento.

Desculpe se isso parece muito óbvio, mas eu sou novo em bash, então, por favor, me perdoe.

Atualizei o script e agora tenho problemas com os episódios 8 e 9. Recebo o seguinte erro

line 10: printf: 08: invalid octal number

Então, os episódios 8 e 9 estão faltando, mas há um arquivo extra S02E00.mkv para cada série com mais de 7 episódios.

O script adaptado

#!/bin/bash
# rename tv show files to kodi friendly format S01E01 etc
cd /mnt/2tb_hd/Adults/TV_Shows/Breaking\ Bad/
if [ $? == 1 ]; then 
    exit
fi
reg='^([^0-9]*)([0-9][0-9]*)[^0-9]*([0-9][0-9]*).*(\....)$'
for filename in *.*; do
      if [[ $filename =~ $reg ]]; then
              printf -v newname 'S%02dE%02d%s' "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" "${BASH_REMATCH[4]}"
                  mv "$filename" "$newname"
                fi
            done
        exit

Veja o link para o resultado completo do teste.

    
por s7ntax 25.08.2016 / 19:09

1 resposta

3

Use printf , com uma string de formato que especifica a largura do campo e o preenchimento com zero para os inteiros, por exemplo,

printf -v newname 'S%02dE%02d%s' "$((10#${BASH_REMATCH[2]}))" "$((10#${BASH_REMATCH[3]}))" "${BASH_REMATCH[4]}"

Observe o uso de $((10#${BASH_REMATCH[n]})) para forçar a avaliação decimal em casos como 09

Teste (modifiquei sua expressão regular ligeiramente BTW):

reg='^([^0-9]*)([0-9][0-9]*)[^0-9]*([0-9][0-9]*)(\....)$'
for filename in *.mp4; do
  if [[ $filename =~ $reg ]]; then
    printf -v newname 'S%02dE%02d%s' "$((10#${BASH_REMATCH[2]}))" "$((10#${BASH_REMATCH[3]}))" "${BASH_REMATCH[4]}"
    echo mv "$filename" "$newname"
  fi
done
mv Some Series01.Episode02.mp4 S01E02.mp4
mv SomeSeries1Episode03.mp4 S01E03.mp4
mv Some_Series.1_Episode.1.mp4 S01E01.mp4


Possivelmente mais robusto seria usar o regex somente para coincidir com as duas primeiras seqüências de dígitos, e usar a substituição de parâmetros do shell para manipular a extensão:

reg='([0-9][0-9]*)[^0-9]*([0-9][0-9]*)'
for filename in *.mp4 *.mkv; do
  name="${filename%.*}"
  ext="${filename##*.}"
  if [[ $name =~ $reg ]]; then
    printf -v newname 'S%02dE%02d.%s' "$((10#${BASH_REMATCH[1]}))" "$((10#${BASH_REMATCH[2]}))" "${ext}"
    echo mv "$filename" "$newname"
  fi
done
mv Some Series01.Episode02.mp4 S01E02.mp4
mv SomeSeries09Episode10.mp4 S09E10.mp4
mv SomeSeries1Episode03.mp4 S01E03.mp4
mv Some_Series.1_Episode.1.mp4 S01E01.mp4
mv Breaking.Bad.S01E01.576p.BluRay.DD5.1.x264-HiSD.mkv S01E01.mkv

Como alternativa, se o seu sistema tiver o comando rename / prename baseado em perl, você poderá fazer algo como

prename -vn -- 's/.*(\d+).*(\d+)/sprintf "S%02dE%02d.mp4", $1, $2/e' *.mp4
    
por 25.08.2016 / 20:15