Renomeador Automático de Arquivos de Mídia
Publicado por Felipe Rafailov 15/07/2009
[ Hits: 6.313 ]
Este script foi criado para renomear arquivos de mídia, como Vídeos e Fotos, porém pode ser utilizado com qualquer tipo de arquivo. É um script bem completo que aceita uma grande variedade de opções de linha de comando.
Para visualizar o resultado sem afetar os arquivos e/ou diretórios, utilize a opção --dummy. Importante usar esta opção para saber como ficariam os arquivos após as transações. Mais informações, incluindo um manual completo com exemplos, pode ser encontrado aqui:
http://maisena.net/scripts/nconv/
#!/bin/bash # Desenvolvido por Felipe Rafailov # E-Mail e GTalk: felipe.rafailov@gmail.com # Quantos diretórios o script irá criar # 0 - Não cria nenhum diretório (ex. Lost S01E01.avi) # 1 - Cria um diretório para o seriado (ex. Lost/S01E01.avi) # 2 - Cria diretórios para o seriado e a temporada (ex. Lost/S01/01.avi) # 3 - Cria um diretório para cada episódio (ex. Lost/S01/S01E01/S01E01.avi) DIRLEVEL=1 #DIRLEVEL=0 # Separador usado para o nome do arquivo e/ou diretório EOW=' ' #EOW='.' #EOW='_' # Cria os diretórios (se necessário) e move o arquivo # 0 - Somente exibe o nome na tela (para visualizar) # 1 - Efetua a transação, movendo o arquivo (padrão) MOVE=1 # Quando habilitado, efetua a cópia do arquivo original para seu novo # destino. COPY=0 # Habilita o modo verboso # 0 - Desabilitado (padrão) # 1 - Habilitado VERBOSE=0 # No modo interativo, em cada alteração o usuário pode aceitar a sugestão, # rejeitar, ou propor outro nome para o arquivo. INTERACTIVE=0 # Os arquivos a serem movidos são armazenados nesta variável FILES= # Quando habilitado, o nome completo será atribuído ao arquivo. # Senão, somente a parte referente ao número do episódio é colocado. # 0 - Nomes curtos, ex.: S01E01.avi # 1 - Nomes compridos, ex.: Lost S01E01.avi FULLNAME=1 # Permite especificar o diretório de saída, onde os arquivos serão # criados. Por padrão, usa-se o diretório atual. #OUTPUT=$PWD OUTPUT= # Permite adicionar um nome (inicial) a todos os arquivos alterados. # Permite também adicionar um contador ao nome, utilizando o caracter # especial '%' BASENAME= COUNT=0 # Esta variável contém uma lista, separada por vírgulas, de todos os termos # a serem ignorados no nome do arquivo. Outra opção, --ignoreall, permite # ignorar completamente o nome original do arquivo. O novo nome será formado # pelo valor de --basedir e --basename. IGNORE= IGNOREALL=0 # Contém o nome do arquivo usado como fonte dos nomes dos episódios, # quando o parâmetro --source é utilizado. O arquivo deve possuir uma # estrutura específica, ex.: # S01E01 Nome do Episódio 1 da 1a temporada SOURCE= # Função responsável por unir duas strings, utilizada para anexara # duas strings consecutivamente, separadas por um caractere ou string # append(){ if [ -n "$1" ]; then if [[ $1 =~ $2$ ]]; then echo "$1" else echo "${1}${3}${2}" fi else echo "$2" fi } # Coloca a primeira palavra em Caixa Alta, quando necessário capitalize(){ if [ ${#1} -ge 3 ] || [[ "$2" =~ ^$1 ]]; then part1="$(echo -n "${1:0:1}" | tr "[:lower:]" "[:upper:]")" part2="$(echo -n "${1:1}" | tr "[:upper:]" "[:lower:]")" echo "${part1}${part2}" else echo "$(echo "$1" | tr "[:upper:]" "[:lower:]")" fi } # Esta função substitui o caractere especial '%' por um contador. Esta função é # utilizada para interpretar o argumento da opção --basename e, no modo # interativo, também a opção de escolher o nome do arquivo manualmente. replace_counter() { NEWCOUNT=$COUNT if [ -n "$1" ] && [[ $1 =~ '(\*?%+)' ]]; then t_mask="${BASH_REMATCH[1]}" if [ "${t_mask:0:1}" = "*" ]; then if [ $INTERACTIVE -eq 1 ]; then NEWCOUNT=1 fi t_mask="${t_mask:1}" else NEWCOUNT=$(($NEWCOUNT+1)) fi t_count=$NEWCOUNT while [ ${#t_count} -lt ${#t_mask} ]; do t_count="0$t_count" done NEWNAME="$(echo "$1" | sed "s/*\?$t_mask/$t_count/")" else NEWNAME="$1" fi echo "NEWNAME=\"$NEWNAME\"" echo "NEWCOUNT=$NEWCOUNT" } show_help(){ echo "Uso: $(basename $0) [-i] [-d] '.' [-l] 3 arquivo1.avi arquivo2.avi ... -h --help Mostra informações resumidas sobre o uso do programa e sai. -v --verbose Mostra informações adicionais na saída, informando o usuário sobre o estado atual da execução. --dummy Mostra as operações que serão realizadas, porém não efetua nenhuma mudança no disco rígido. Também implica em -v. -s --short Utiliza nomes curtos para os arquivos. -c --copy Copia o arquivo original para seu novo destino, em vez de movê-lo. Útil para quando os arquivos originais estiverem em mídias de somente-leitura (CD's ou DVD's). -i --interactive Habilita o modo interativo, que permite visualizar as alterações a serem realizadas no disco rígido antes de aceitá-las. --ignore a,b,c Permite especificar uma lista (separada por vírgulas) de termos que não serão consideradas como parte do novo nome do arquivo. Esta opção não distingue maiúsculas/minúsculas. --ignoreall Ignora completamente o nome original do arquivo. O novo nome deverá ser baseado nos valores de --basename e --basedir. -d --delimiter d Altera o caractere delimitador. Por padrão, usa-se espaço. --basename n Permite adicionar um nome ao início de cada arquivo a ser alterado. Você pode acicionar um contador com o caractere '%'. Usando-o múltiplas vezes seguidas permite adicionar mais dígitos ao contador. Ex.: --basename '%%' = 01, --basename '%%%' = 001, etc. --basedir n Permite especificar o diretório de base onde os novos diretórios e arquivos serão criados. --source file Esta opção permite especificar um arquivo para servir de fonte para os nomes dos episódios. O arquivo deve possuir o seguinte formato: S01E01 Nome do Episódio 1 da 1a Temporada -l --level l Altera o número de sub-diretórios que serão criados. Aceita valores de 0-3. O padrão é 1. Por exemplo: nível 0: Lost S01E01.avi nível 1: Lost/Lost S01E01.avi nível 2: Lost/S01/Lost S01E01.avi nível 3: Lost/S01/S01E01/Lost S01E01.avi" } # Faz a leitura das opções de linha de comando do script while [ -n "$1" ]; do case "$1" in -h | --help) show_help exit 0 ;; -v | --verbose) VERBOSE=1 ;; -i | --interactive) MV_OPTS="-i" INTERACTIVE=1 ;; --dummy) MOVE=0 VERBOSE=1 ;; -s | --short) FULLNAME=0 ;; -c | --copy) COPY=1 ;; -d | --delimiter) shift if [ "$1" = '/' ]; then echo ERRO: Delimitador inválido exit 1 fi EOW="$1" ;; --basedir) shift # Não é necessário verificar o diretório de saída, isso é feito mais adiante OUTPUT="$(echo $1 | sed 's/\/$//')" ;; --basename) shift BASENAME="$1" ;; --source) shift if [ -f "$1" ] && [ -r "$1" ]; then SOURCE="$1" else echo "AVISO: Não pode ler do arquivo de fonte $1" fi ;; --ignore) shift IGNORE=",$(echo "$1" | sed 's/[[:space:]]\+/,/g')," ;; --ignoreall) IGNOREALL=1 ;; -l | --level) shift if [[ $1 =~ ^[[:digit:]]+$ ]] && [ $1 -ge 0 ] && [ $1 -le 3 ]; then DIRLEVEL=$1 else echo "ERRO: Nível inválido. Utilize valores de 0 a 3." echo "Veja $(basename $0) --help para maiores informações." exit 1 fi ;; *) FILES=$(append "$FILES" "$1" \;) ;; esac shift done # Verifica se foram passados arquivos como parâmetro if [ -z "$FILES" ]; then echo ERRO: Nenhum arquivo fornecido para renomear exit 1 fi # Caso alguma das opções, --basedir ou --basename for usada, faz # o tratamento do nome, como espaços. if [ -n "$OUTPUT" ]; then OUTPUT="$(echo $OUTPUT | sed "s/[[:space:]]\+/${EOW}/g")" fi if [ -n "$BASENAME" ]; then BASENAME="$(echo $BASENAME | sed "s/[[:space:]]\+/${EOW}/g")" fi # A variável IFS é alterada pois no caso da variável FILES, os arquivos # são separados por ponto-e-vírgula ';' IFS=';' for file in $FILES; do # O nível de expansão pode variar conforme o nome do arquivo. Caso não seja # encontrado um número de episódio, um nível inferior (1) é usado. t_dirlevel=$DIRLEVEL t_short=$FULLNAME t_basename="$BASENAME" # Pula arquivos não existentes e diretórios (quando não estiver usando --dummy) if [ -d "$file" ] || [ $MOVE -eq 1 ] && [ ! -f "$file" ]; then if [ -d "$file" ]; then echo "ERRO: \"$file\" é um diretório." elif [ ! -f "$file" ]; then echo "ERRO: Arquivo não encontrado: \"$file\"" fi continue fi # Verifica o diretório de saída (quando especificado) ou o diretório atual if [ -n "$OUTPUT" ]; then t_ckdir="$OUTPUT" else t_ckdir=$PWD fi while [ ! -d $t_ckdir ]; do t_ckdir="$(dirname "$t_ckdir")" done if [ ! -w "${t_ckdir}" ] && [ $MOVE -eq 1 ]; then echo "ERRO: Não posso criar arquivo(s)/diretório(s) de saída em $t_ckdir" exit 1 fi t_filename="$(basename "$file")" t_extension="$(echo $t_filename | awk -F . '{print $NF}')" # Verifica se o arquivo possui extensão if [ "$t_filename" = "$t_extension" ]; then unset t_extension else t_extension=".$t_extension" fi if [ $IGNOREALL -eq 0 ]; then t_filename=$(basename "$file" "$t_extension" | sed 's/[[:punct:]]\+/ /g') else unset t_filename fi unset IFS for t_part in $t_filename ; do # Remove partes indesejadas do nome do arquivo, passadas pelo argumento # --ignore t_check="$(echo "$t_part" | sed "s/[[:digit:]]/%/g")" if [ -n "$(echo $IGNORE | grep -i ",$t_check,")" ] || [ -n "$(echo $IGNORE | grep -i ",$t_part,")" ]; then continue # Procura pelo descritivo do número do episódio, geralmente # SXXEYY, onde XX é a temporada e YY é o número do episódio. # Ex.: S01E01 elif [[ $t_part =~ ^[sS]?[[:digit:]]+[eE]?[[:digit:]]*$ ]]; then filename="$(append "$filename" "$(echo $t_part | tr se SE)" "$EOW")" break # Caso seja um nome composto alfanumérico, do tipo arquivo01 elif [[ $t_part =~ ^([[:alpha:]]+)([[:digit:]]+)$ ]]; then t_alpha_part="${BASH_REMATCH[1]}" t_numeric_part="${BASH_REMATCH[2]}" t_check="$(echo "$t_numeric_part" | sed "s/[[:digit:]]/%/g")" if [ -n "$(echo $IGNORE | grep -i ",$t_alpha_part,")" ] || [ -n "$(echo $IGNORE | grep -i ",$t_check,")" ] || [ -n "$(echo $IGNORE | grep -i ",$t_numeric_part,")" ]; then continue else t_part="$(capitalize "$t_alpha_part" "$t_filename")" dirname="$(append "$dirname" "$t_part" "$EOW")" filename="$(append "$filename" "$t_numeric_part" "$EOW")" fi else t_part="$(capitalize "$t_part" "$t_filename")" dirname="$(append "$dirname" "$t_part" "$EOW")" fi done # Quando o nome do diretório for vazio, altera o t_dirlevel para # compensar a falta do nome if [ -z "$dirname" ] && [ -n "$filename" ]; then if [ $t_dirlevel -eq 1 ]; then t_dirlevel=2 elif [ $t_dirlevel -eq 2 ]; then t_dirlevel=3 fi fi # Caso o nome do arquivo (filename) esteja vazio, este recebe o nome do # diretório if [ -z "$filename" ] && [ -n "$dirname" ]; then filename="$dirname" if [ $t_dirlevel -gt 1 ]; then t_dirlevel=1 fi fi # Altera o nome entre o nome curto e longo, de acordo com a # opção --short. Também verifica se o nome do diretório e do arquivo # são iguais, para evitar nomes repetidos. if [ $t_short -eq 1 ] && [ ! "$dirname" = "$filename" ]; then t_fullname="$(append "$dirname" "$filename" "$EOW")" else t_fullname=$filename fi # Caso exista um prefixo (--basename), verificar a existencia do # caracter de contador e substituí-lo pelo número do contador eval "$(replace_counter "$t_basename")" t_basename="$NEWNAME" COUNT=$NEWCOUNT # Adiciona um prefixo a todos os arquivos alterados (usando a opção --basename) t_fullname="$(append "$t_basename" "$t_fullname" "$EOW")" # Quando estiver usando a opção --source, obter o nome do episódio através do # arquivo de fonte especificado pelo parâmetro, tratar a entrada e anexar este # no nome do arquivo. if [ -n "$SOURCE" ] && [[ $filename =~ ^S?[[:digit:]]+E?[[:digit:]]*$ ]]; then t_episode="$(cat "$SOURCE" | grep "$filename" | cut -d' ' -f2- | sed "s/[[:space:]]\+/${EOW}/g")" t_fullname="$(append "$t_fullname" "$t_episode" "$EOW")" fi # Verifica se o nome do arquivo é vazio. Caso seja, significa que o script falhou # em determinar o nome do arquivo, logo ele será ignorado if [ -z "$t_fullname" ]; then echo "ERRO: Falha ao determinar nome do arquivo. Pulando arquivo $file" continue else # Adiciona a extensão do arquivo no nome completo t_extension="$(echo $t_extension | tr "[[:upper:]]" "[[:lower:]]")" t_fullname="$(append "$t_fullname" "$t_extension")" fi # Caso o DIRLEVEL seja maior ou igual a 2, o seguinte código descobre o nome do # diretório intermediário, que é formado pelos primeiros dígitos numéricos do # código do episódio, ou, no caso de somente haver números, usa-se a dezena ou # centena. # Ex.: # S01E01 => S01 # 115 => 100 if [ $t_dirlevel -ge 2 ] && [[ $filename =~ ^(S?[[:digit:]]+) ]]; then t_midname=${BASH_REMATCH[1]} if [ ! "${t_midname:0:1}" = "S" ]; then t_size=${#t_midname} if [ $t_size -le 2 ]; then if [ $t_size -eq 1 ]; then t_midname="$(append "0" "$t_midname")" fi t_size=1 else t_size=$(expr ${#t_midname} - 2) fi t_xpon=$((10**$t_size)) t_midname=$(expr $t_midname - $(expr $t_midname % $t_xpon)) fi fi # Estabelece o nível de diretórios de acordo com a variável # DIRLEVEL (t_dirlevel) case $t_dirlevel in 0) newname="$t_fullname" ;; 1) newname="$(append "$dirname" "$t_fullname" \/)" ;; 2) filename="$(append "$t_midname" "$t_fullname" \/)" newname="$(append "$dirname" "$filename" \/)" ;; 3) filename="$(append "$t_midname" "$filename" \/)" filename="$(append "$filename" "$t_fullname" \/)" newname="$(append "$dirname" "$filename" \/)" ;; esac # Permite adicionar um diretório de saída usando a opção --basedir newname="$(append "$OUTPUT" "$newname" \/)" # Se no modo interativo, permite ao usuário aceitar o nome, rejeitar, # ou propor um nome próprio. O usuário também pode cancelar o modo # iterativo e sair do programa. t_exit=0 t_skip=0 while [ $INTERACTIVE -eq 1 ] && [ $t_exit -eq 0 ]; do echo if [ $COPY -eq 1 ]; then t_action=Copiar else t_action=Mover fi echo $t_action \"$file\" \=\> \"$newname\" echo -n "Escolha uma opção, ou ? para ajuda: " read t_option while [[ ! $t_option =~ ^[12345?arpcsARPCS]$ ]]; do echo "Opção Inválida: $t_option" read t_option done case $t_option in a | A | 1) t_exit=1 ;; r | R | 2) unset dirname unset filename IFS=';' t_exit=1 t_skip=1 ;; p | P | 3) echo -n "Digite o nome do arquivo: " read t_newname while [ -z "$t_newname" ]; do echo -n "Digite o nome do arquivo: " read t_newname done eval "$(replace_counter "$t_newname")" newname="$(echo $NEWNAME | sed "s/[[:space:]]\+/${EOW}/g")" COUNT=$NEWCOUNT t_exit=1 ;; c | C | 4) INTERACTIVE=0 unset MV_OPTS t_exit=1 ;; s | S | 5) exit 0 ;; ?) echo Opção 1. a Aceitar nome escolhido, alterar nome do arquivo echo Opção 2. r Rejeitar nome escolhido, manter nome original echo Opção 3. p Propor outro nome para o arquivo echo Opção 4. c Cancelar o modo interativo, continuar no automático echo Opção 5. s Sair do programa ;; esac done if [ $t_skip -eq 1 ]; then continue fi t_return=0 # Move/renomeia o arquivo para seu novo destino e cria o diretório caso # seja necessário if [ $MOVE -eq 1 ]; then t_newdir=$(dirname "$newname") if [ ! -d "$t_newdir" ] && [ ! -f "$t_newdir" ]; then mkdir -p "$t_newdir" fi if [ $COPY -eq 1 ]; then t_cmd=cp else t_cmd=mv fi $t_cmd $MV_OPTS "$file" "$newname" t_return=$? fi # Habilita a saída em modo verboso if [ $VERBOSE -eq 1 ]; then [[ $t_return -ne 0 ]] && echo -n "ERRO: " || echo -n "OK: " echo $newname fi # Limpa as variáveis utilizadas unset dirname unset filename IFS=';' done
Atualizando o sistema no Debian
Script para ripar faixas de CDs e codificar para .ogg
Colocar palavras em minúsculas
Restaurar base de dados PostgreSQL
Script de instalação Servidor MTA Postfix + Openwebmail
Passkeys: A Evolução da Autenticação Digital
Instalação de distro Linux em computadores, netbooks, etc, em rede com o Clonezilla
Título: Descobrindo o IP externo da VPN no Linux
Armazenando a senha de sua carteira Bitcoin de forma segura no Linux
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Instalando Brave Browser no Linux Mint 22
vídeo pra quem quer saber como funciona Proteção de Memória:
Encontre seus arquivos facilmente com o Drill
Mouse Logitech MX Ergo Advanced Wireless Trackball no Linux
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
PC não liga no filtro de linha (3)
Desde que seja DDR3, posso colocar qualquer memória? (3)
Instalar sem formatar, pergunta meio boba. [RESOLVIDO] (7)
Curso gratuito Defesa de redes 10ª Maratona CiberEducação Cisco Brasil... (0)