Como remover caracteres finais nos nomes de arquivos no Bash?

13

Eu tenho vários arquivos de mídia como os abaixo:

tvshow.s01e11]Bloodlines.avi
tvshow.s01e12]suffer.avi
tvshow.s01e13]NotMe.avi

Eu gostaria de renomeá-los para

tvshow.s01e11.avi
tvshow.s01e12.avi
tvshow.s01e13.avi

Eu tentei usar renomear, mas evidentemente não estou conseguindo a sintaxe correta, porque ela falha.

Widgeteye
fonte
Se você quiser fazer isso em um gui, krenameé adorável. Ele tem todos os tipos de opções poderosas e mostra o que ele fará antes que realmente o faça. Você pode usá-lo para testar padrões que você pode usar no bash mais tarde.
Joe

Respostas:

14

No shell, pode-se fazer simplesmente:

for x in *]*.avi ; do 
    mv -i "$x" "${x%]*.avi}.avi"
done

O shell pode produzir uma lista dos nomes de arquivos com apenas um glob regular e ${var%pattern}remove o padrão de correspondência (mais curto) do final da string na variável var. Como a extensão final é sempre .avi, eu apenas a removi com o padrão e a adicionei novamente. Com as aspas, isso também deve funcionar com nomes de arquivos que contenham espaços, comoFancy Name for a Show.s01e01]Asdf.avi

ilkkachu
fonte
@NoviceC o padrão extglob não era uma má ideia. Na verdade, algo como ${x/]*([^.])}deveria fazer, remove um suporte e qualquer número de não-pontos. (embora não se há outras faixas ou pontos, uma vez que não está bloqueado para o final do string)
ilkkachu
Este é um bom ponto. Mas realmente compliquei demais o problema quando deveria ter ido ${x/]*.avi}e adicionei um .avicomo você. Mas eu também estava insatisfeito com a forma como os espaços no nome iriam se romper (`find . -name '*]*.avi'`). Fiquei feliz em fornecer um método limitado limitado de comando unix, já que renomear não é, mas isso explode o meu na água.
Novice C
2

Isso é impraticável - as outras respostas são muito mais rápidas e curtas - mas ...

Você pode usar o PowerShell! A Microsoft fez o código-fonte aberto recentemente e o tornou multiplataforma. Para obter instruções sobre downloads e instalação do seu sistema operacional, consulte a seção "Obter PowerShell" .

Depois de instalá-lo, você pode usar este breve script:

Get-ChildItem -File '*]*.avi' | ForEach-Object {
    Rename-Item $_ -NewName (($_.Name -Split ']')[0] + '.avi')
}

Basicamente, ele percorre cada objeto no diretório atual que corresponde a um arquivo *]*.avi, obtém a peça antes do colchete, recolhe-o .avinovamente e atribui isso como o novo nome.

Para executá-lo diretamente do Bash, use este liner semi-golfado:

powershell -command $'gci -File \'*]*.avi\'|%{rename-item $_ -NewName (($_.Name -Split \']\')[0]+\'.avi\')}'

As citações que escapam são cortesia desta resposta do Stack Overflow .

(Testado no Bash no Ubuntu no Windows. Provavelmente, existe uma maneira muito mais curta de fazer isso com o PowerShell, mas eu queria mostrar algo compreensível para as pessoas que não conhecem expressões regulares.)

Ben N
fonte
Rube Goldberg ficaria orgulhoso! Regexes são uma verdadeira PITA para aprender, mas valem a pena muitas vezes - mesmo no nível rudimentar em que posso usá-las.
Joe
1

O Debian possui um pacote chamado mmv, que também pode estar disponível em outras distribuições, e deve ser fácil o suficiente para compilar a partir do código-fonte, caso contrário. Ele permite que você escreva isso:

mmv '*]*.avi' '#1.avi'

Você pode ler a página de manual do Ubuntu para este comando para obter mais detalhes.

MvG
fonte
0

Isso procurará o padrão e substituirá o texto usando sed.

 $sed 's/\(.*]\)[a-zA-z0-9].*\(.avi\)/\1\2/' filename
Tejender Mohan
fonte