Desejo renomear vários arquivos no mesmo diretório usando script Bash. Os nomes dos arquivos são os seguintes:
file2602201409853.p file0901201437404.p file0901201438761.p file1003201410069.p file2602201410180.p
Desejo renomear para o seguinte formato:
file2503201409853.p file2503201437404.p file2503201438761.p file2503201410069.p file2503201410180.p
Eu estava lendo sobre o comando renomear e tento fazer dessa forma, mas não adianta nada, acho que tenho dúvidas sobre a sintaxe. Então eu li que você pode fazer um loop usando o comando mv da seguinte maneira:
for file in cmpsms*2014*.p; do mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}" done
Mas não consigo renomear os arquivos. O que estou fazendo de errado?
Comentários
Resposta
Você estava certo ao considerar renomear primeiro. A sintaxe é um pouco estranha se você não está acostumado a regexes, mas é de longe o caminho mais rápido / mais curto depois que você sabe o que está fazendo:
rename "s/\d{4}/2503/" file*
Isso simplesmente corresponde aos primeiros 4 números e os troca pelos que você especificou.
E um equipamento de teste (-vn
significa ser prolixo, mas não faça qualquer coisa) usando seus nomes de arquivo:
$ rename "s/\d{4}/2503/" file* -vn file0901201437404.p renamed as file2503201437404.p file0901201438761.p renamed as file2503201438761.p file1003201410069.p renamed as file2503201410069.p file2602201409853.p renamed as file2503201409853.p file2602201410180.p renamed as file2503201410180.p
Comentários
- Observação que esta é a renomeação Perl no Debian e derivados (Ubuntu, Mint, …). Em outras distribuições do Linux,
rename
é uma ferramenta de renomeação de arquivo completamente diferente (que o Debian fornece comorename.ul
). - Se você não tiver essa ferramenta distributiva, veja a resposta de @Michael Campbell Acho que todo padrão de substituição distributiva
rename
como o debian fez.
Resposta
Isso deve funcionar:
for f in file*; do mv $f ${f/${f:4:8}/25032014}; done
Ele substitui a string entre o 4º e o 12º caractere por “25032014”.
Comentários
- isso
for f in file*; do mv $f ${f/${f:4:4}/2503}; done
também funciona. - Isso ' é bom. Se você deseja apenas fazer uma substituição regular de palavra por palavra, funciona como o sed. por exemplo.
for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
- @Eric – Postei sua resposta como alternativa porque acho ' mais clara e elegante . Se você também quiser postá-lo como uma resposta – eu ' excluirei o meu. Obrigado!
- Por que aspas duplas ausentes ?
- Isso me deu um erro: " mv: target ' FILE_NAME ' não é um diretório "
Resposta
esta é realmente a resposta de @Eric “acima – mas é uma resposta elegante, então Estou publicando-a novamente como uma resposta adequada para chamar mais atenção para ela.
for f in *Huge*; do mv "$f" "${f/Huge/Monstrous}"; done
Resposta
ptrn="file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p" path=/dir ( set -- "${path}/"${ptrn} ; for f ; do { echo "mv ${path}/${f} \ ${path}/file25032014${f#2014}" } ; done )
Isso deve funcionar. Observação – não tenho o hábito de entregar comandos de mv em massa – conforme está escrito,” é apenas um eco. Você ” terá que resolver isso antes de “funcionar.
Resposta
Uma maneira nativa simples de fazer isso sem loop, com travessia de diretório :
find -type f | xargs -I {} mv {} {}.txt
Ele renomeará todos arquivo no lugar.
E abaixo de uma obra exemplo de ing com paralelização :
find -name "file*.p" | parallel "f="{}" ; mv -- {} ${f:0:4}2503${f:8}"
Comentários
- Foi uma primeira abordagem fácil para imaginar uma solução melhor. Se você deseja um comando funcional, faça:
-
find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
Resposta
Se você acha que faz muito esse tipo de coisa, pesquise “rename.pl”. É um script perl, mas permite que você simplesmente o alimente com código perl (como /// expression), e ele fará uma renomeação em massa com base nessa expressão ou código.
Há uma versão básica aqui: http://stackoverflow.org/wiki/Rename.pl mas existem outras versões flutuando na rede. Ele existe há muito tempo.
*
está?