Script de shell Bash para localizar e remover a substring dentro de um nome de arquivo

4

Estou tentando escrever um script de shell bash no Mac OS X 10.6 (que é chamado por uma ação do Automator) para renomear os rasgos de DVD de programas de TV que chamei mal ao longo dos anos. Eu quero remover parte do texto nos nomes dos arquivos. Eu quero remover o texto que aparece após uma série específica de caracteres que eu sei que sempre aparecerá no nome do arquivo. Mas não sei quantos caracteres aparecerão antes ou depois da conhecida série de caracteres. Também não sei se o texto anterior ou posterior conterá vários períodos ou traços. Um exemplo provavelmente ajudaria:

The.Big.Bang.Theory.S01E01.xxxxxxxxxxx.mp4

Eu sei que cada arquivo sempre conterá uma string no formato de SxxExx, onde os xs são sempre números. Mas eu não sei quais serão os números. Eu quero pegar o nome do arquivo até e incluindo a string SxxExx e a extensão do arquivo, mas remover todo o resto. Então, para o exemplo acima, eu acabaria com:

The.Big.Bang.Theory.S01E01.mp4

Eu tentei usar os comandos internos de substituição de string do bash. Eu pensei que o comando expr index me daria o ponto inicial da string SxxExx e então eu poderia usar $ {filename: offset: length} para extrair apenas a parte requerida do nome do arquivo (eu já conheço a extensão para que possa adicionado). Mas parece que a versão OS X da expr não inclui a funcionalidade do índice. Eu tenho apenas script em Basic e LotusScript antes. Nesses ambientes, isso seria bastante fácil usando comandos como 'Like' e 'Instr' ou 'Mid'. Mas no bash eu simplesmente não consigo entender. Eu passei horas procurando no Google, tentando entender como usar expressões regulares para localizar a substring 'SxxExx' no nome do arquivo, mas eu simplesmente não consigo descobrir. Espero que alguns scripts inteligentes do UNIX possam me ajudar!

    
por Stu 22.08.2011 / 13:19

2 respostas

5

Tente isto:

newname='echo "$filename" | sed -e 's/\(S[0-9][0-9]E[0-9][0-9]\).*\.mp4/.mp4/''

A expressão regular é:

  • inicie um grupo (\ ()
  • corresponde a SXXEXX, em que X é um numeral entre 0 e 9
  • end group (\))
  • corresponde a qualquer número de qualquer caractere (exceto uma nova linha)
  • corresponde a uma string explícita (.mp4)

Na expressão de substituição:

  • substituir pela string correspondida no primeiro grupo (\ 1)
  • substituir por cadeia de caracteres explícita (.mp4)
por 22.08.2011 / 14:22
4

Supondo que você tenha uma lista de nomes de arquivos com caminhos no arquivo file-list , tente o seguinte

while IFS= read -r path; do
  newpath=$(printf '%s\n' "$path" |
    sed 's/\(.*S[0-9]*E[0-9]*\.\).*\.\([^.]*\)$//')
  echo mv -- "$path" "$newpath"
done <file-list

Significado da expressão regular sed usada, também comparada com o exemplo de entrada "The.Big.Bang.Theory.S01E01.xxxxxxxxxxx.mp4"

\(                               start of group 1
.*        The.Big.Bang.Theory.   any sequence of characters
S[0-9]*   S01                    a capital S followed by 0 or more digits
E[0-9]*   E01                    a capital E followed by 0 or more digits
\.        .                      a dot
\)                               end of group 1
.*        xxxxxxxxxxx            any sequence of characters
\.        .                      a dot
\(                               start of group 2
[^.]*     mp4                    a sequence of 0 or more non-dot characters
\)                               end of group 2
$                                end of line

Na saída, a string significa "grupo de saída1 seguido por grupo2 (portanto, para remover xxxxxxxxxxx. )

Remova o echo , se estiver satisfeito.

    
por 22.08.2011 / 14:21