Renomeação de arquivo em lote baseada em padrão no terminal

48

Preciso renomear o seguinte:

file_001_loremipsum.png
file_002_dolor.png
file_003_sit.png
file_004_amet.png
file_105_randomness.png

para dentro

upl_loremipsum.png
upl_dolor.png
upl_sit.png
upl_amet.png
upl_randomness.png

Como faço isso acontecer com apenas uma linha simples de comando do terminal?

Unamata Sanatarai
fonte
1
Uma versão à prova de falhas com base em regex python que funciona recursivamente em todas as subpastas: stackoverflow.com/a/39698169/191246
ccpizza

Respostas:

79

A solução para o exemplo acima, usando renomear :

rename -v -n 's/file_\d{1,3}/upl/' file_*.png

Uso:

rename [options] [Perl regex search/replace expression] [files]

De man rename:

   -v, --verbose
           Verbose: print names of files successfully renamed.
   -n, --no-act
           No Action: show what files would have been renamed.

renomear PODE tomar regex como os argumentos.

O que estamos vendo é o conteúdo entre aspas simples '. Você pode colocar regex separado por /.

Fórmula: s/(1)/(2)/onde (1)= padrão de pesquisa e (2)= substituir padrão.

Portanto, familiarize-se com o regex e aproveite a renomeação de arquivos em lote com base em padrões!

Unamata Sanatarai
fonte
14
Eu sei que este é o Ubuntu, mas se alguém acabar aqui, mesmo procurando uma solução OS X (eu fiz), renameé facilmente instalado brew install rename.
Sandstrom
No Ubuntu 18.10, a --no-actbandeira está em seu --nonolugar. Essa resposta também pode ser um pouco mais explícita: [files]refere-se a um padrão inicial que corresponde aos arquivos no diretório atual que se deseja renomear (por exemplo, *corresponde a tudo, mas apenas no diretório atual).
Patrick Dark
Seu link aponta para outro rename, que possui formato rename from to filee não suporta expressões regulares. Na verdade, minha distribuição Linux (Cent OS 7) tem exatamente essa versão.
Alex Che
6

se os arquivos estiverem nos diretórios de severais, use renomear após uma descoberta como:

find -iname file_*.png -type f -exec rename -n 's/file_[0-9]{3}(.*\.png)/upl$1/' {} \;

o -n depois de renomear é testar, remova-o para continuar! -)

assim, você associa encontrar e renomear poder.

Pessoalmente, usei-o para renomear o cabeçalho de fontes .h para .hpp

find -iname *.h -type f -exec rename 's/(.*\.)h/$1hpp/' {} \;
bcag2
fonte
Não há documentação para o -iname, -typee -execbandeiras em manpages.ubuntu.com/manpages/bionic/man1/find.1.html#expression . ( find --helpnão é particularmente útil para este comando.) TL; DR: -inamecorresponde a um padrão sem distinção entre maiúsculas e minúsculas; -type fcorresponde a "arquivos regulares"; e -execexecuta uma expressão até encontrar um ;caractere (ponto e vírgula).
227 Patrick Patrick Dark
5

Isso pode ser feito com pouca mágica da expansão dos parâmetros do bash!

for f in file_[0-9]*_*; do mv $f upl_${f#file_[0-9]*_}; done

file_[0-9]*_*;- O primeiro padrão é usado para percorrer todos os arquivos que começam com 'file_anynumber_'
${f#file_[0-9]*_}- O segundo padrão file_[0-9]*_é usado na expansão de parâmetros que informa ao bash para remover 'file_anynumber_' do início da string.

Para mais informações sobre Parameter expansion:

man bash
Basharat Sialvi
fonte
Observe que isso usa globs, não regex, portanto [0-9]*, corresponderá a um dígito seguido por qualquer sequência. Provavelmente existe uma maneira melhor de combinar apenas números, mas não consigo pensar em nada sucinto.
Wjandrea
Você também seria capaz de sugerir uma maneira de fazer com que esse comando funcione recursivamente em todos os subdiretórios?
Francesco DM