Renomear arquivos em massa

25

Eu tenho vários arquivos:

10.3.100.179_01_20161018_230014_5335.jpg
10.3.100.179_01_20161018_231514_0814.jpg
10.3.100.179_01_20161018_233014_5706.jpg
10.3.100.179_01_20161018_234514_0896.jpg
10.3.100.179_01_20161018_230114_5395.jpg
10.3.100.179_01_20161018_231614_1145.jpg
10.3.100.179_01_20161018_233114_6047.jpg
10.3.100.179_01_20161018_234614_0547.jpg
10.3.100.179_01_20161018_230114_5492.jpg
10.3.100.179_01_20161018_231614_1264.jpg
10.3.100.179_01_20161018_233114_6146.jpg
10.3.100.179_01_20161018_234614_0658.jpg
10.3.100.179_01_20161018_230214_5630.jpg
10.3.100.179_01_20161018_231714_7135.jpg

Eu quero renomear com este formato:

10.4.100.135_01_20161013131108389_TIMING.jpg
10.4.100.135_01_20161013131111390_TIMING.jpg
10.4.100.135_01_20161013131114401_TIMING.jpg
10.4.100.135_01_20161013131117431_TIMING.jpg
10.4.100.135_01_20161013131120418_TIMING.jpg
10.4.100.135_01_20161013131123461_TIMING.jpg
10.4.100.135_01_20161013131126511_TIMING.jpg

Ele precisa remover o _registro de data e hora e adicionar o _TIMING.

Jojo Mendoza
fonte
5
Por favor, use exemplos consistentes em suas perguntas. Parece que você deseja substituir 10.3.100.179com 10.4.100.135. É isso que você quer ou apenas deseja remover da _TIMINGe _da época?
terdon 21/10
3
É um bom momento para lembrar às pessoas que existe um padrão iso8601 para datas (que funciona tanto para nomes de arquivos quanto para entradas de log) ^^ Portanto, talvez você deva reconsiderar a renomeação para: AAAA-MM-DDThh: mm: ss.mmm (ex : seu primeiro arquivo se tornaria: 10.4.100.135_01_2016-10-13T13:11:08.389_TIMING.jpg(e "TIMING" poderia até ser removido, pois agora parece claramente uma data e hora (e milissegundos), especialmente quando o padrão se torna mais difundido. OT faz parte do padrão e eu cresceu para como ele (e retirá-lo quebra o padrão ^^)
Olivier Dulac
@OlivierDulac Eu não recomendaria o uso :de um nome de arquivo. Eu acredito que o Windows não suporta isso.
23718 Justin Justin
@ Justin bom ponto. o padrão recomenda removê-lo para nomes de arquivos. Eu dei a versão em arquivo #
Olivier Dulac

Respostas:

38

Instale renameutilse use qmvcom seu editor de texto favorito.

qmvcarrega todos os nomes no seu editor e, quando você salva e fecha, aplica suas alterações nos arquivos reais. Se as alterações forem inconsistentes (por exemplo, dois arquivos têm o mesmo nome), ela será abortada sem tocar em nada. Ele também lida com renomeação circular corretamente.

Eu costumo fazer:

$ qmv -f do

para mostrar apenas uma coluna de nomes (faça: somente destino). Veja como fica:

qmw

Se você combiná-lo com os vários cursores do SublimeText, Atom ou Visual Studio Code, cria uma ferramenta muito agradável e poderosa para renomear em massa. Por exemplo, para Atom, você faria EDITOR="atom -w" qmv -f do.

ateijelo
fonte
1
Bem-vindo ao askUbuntu! Isso é tão legal!
αғsнιη
Assinou apenas para +! isto. ;)
J. Allan
2
Uau, boa ferramenta e boa animação GIF. Ótima primeira resposta, seja bem-vindo! :)
Byte Commander
1
Obrigado @KasiyA por incluir a imagem e obrigado a todos pelos comentários positivos.
precisa saber é
1
@kasperd Sim, ele avisa que o plano de renomeação contém erros e abre um console interativo onde outras ações podem ser tomadas.
ateijelo
27

Use rename...

rename -n 's/^([0-9]+\.[0-9]\.[0-9]+\.[0-9]+_[0-9]+_)([0-9]+)_([0-9]+)_([0-9]+)\.jpg/$1$2$3$4_TIMING\.jpg/' *

Com -nisso, o resultado será o que será feito sem fazer alterações:

rename(10.3.100.179_01_20161018_230014_5335.jpg, 10.3.100.179_01_201610182300145335_TIMING.jpg)
rename(10.3.100.179_01_20161018_231514_0814.jpg, 10.3.100.179_01_201610182315140814_TIMING.jpg)
rename(10.3.100.179_01_20161018_233014_5706.jpg, 10.3.100.179_01_201610182330145706_TIMING.jpg)
rename(10.3.100.179_01_20161018_234514_0896.jpg, 10.3.100.179_01_201610182345140896_TIMING.jpg)

Se parecer correto, remova o -n

$ rename 's/^([0-9]+\.[0-9]\.[0-9]+\.[0-9]+_[0-9]+_)([0-9]+)_([0-9]+)_([0-9]+)\.jpg/$1$2$3$4_TIMING\.jpg/' *
$ ls
10.3.100.179_01_201610182300145335_TIMING.jpg  10.3.100.179_01_201610182330145706_TIMING.jpg
10.3.100.179_01_201610182315140814_TIMING.jpg  10.3.100.179_01_201610182345140896_TIMING.jpg

Explicando ...

  • s/something/something_else/ pesquisar e substituir
  • ^ o começo do nome (ancoragem)
  • [0-9] qualquer número
  • + um ou mais caracteres anteriores
  • \.literal .(sem \isso corresponde a nenhum caractere)
  • () para manter essa parte
  • $1$2$3$3 referências anteriores às coisas correspondidas anteriormente e mantidas com ()

Nota: o *final do comando corresponde a todos os arquivos visíveis no diretório atual. Use um globo mais adequado, se necessário.

Zanna
fonte
2
Em algumas distribuições, este comando está disponível como prename(p para perl, porque o primeiro argumento é uma expressão perl)
Peter Cordes
12

mmv pode fazê-lo da seguinte maneira:

mmv '*_*_*_*_*.jpg' '#1_#2_#3#4#5_TIMING.jpg'

10.3.100.179_01_20161018_230014_5335.jpg 10.3.100.179_01_201610182300145335_TIMING.jpg

# 1, # 2, # 3, ... está referenciando cada um ao '*' correspondente aqui.

É ainda mais curto com:

mmv '*_*_*.jpg' '#1#2#3_TIMING.jpg'
αғsнιη
fonte
9

Outra renameabordagem:

$ rename -n 's/(.*)_(.*)_(.*)\./$1$2$3_TIMING./' *
10.3.100.179_01_20161018_230014_5335.jpg -> 10.3.100.179_01_201610182300145335_TIMING.jpg
10.3.100.179_01_20161018_230114_5395.jpg -> 10.3.100.179_01_201610182301145395_TIMING.jpg
10.3.100.179_01_20161018_230114_5492.jpg -> 10.3.100.179_01_201610182301145492_TIMING.jpg
10.3.100.179_01_20161018_230214_5630.jpg -> 10.3.100.179_01_201610182302145630_TIMING.jpg
10.3.100.179_01_20161018_231514_0814.jpg -> 10.3.100.179_01_201610182315140814_TIMING.jpg
10.3.100.179_01_20161018_231614_1145.jpg -> 10.3.100.179_01_201610182316141145_TIMING.jpg
10.3.100.179_01_20161018_231614_1264.jpg -> 10.3.100.179_01_201610182316141264_TIMING.jpg
10.3.100.179_01_20161018_231714_7135.jpg -> 10.3.100.179_01_201610182317147135_TIMING.jpg
10.3.100.179_01_20161018_233014_5706.jpg -> 10.3.100.179_01_201610182330145706_TIMING.jpg
10.3.100.179_01_20161018_233114_6047.jpg -> 10.3.100.179_01_201610182331146047_TIMING.jpg
10.3.100.179_01_20161018_233114_6146.jpg -> 10.3.100.179_01_201610182331146146_TIMING.jpg
10.3.100.179_01_20161018_234514_0896.jpg -> 10.3.100.179_01_201610182345140896_TIMING.jpg
10.3.100.179_01_20161018_234614_0547.jpg -> 10.3.100.179_01_201610182346140547_TIMING.jpg
10.3.100.179_01_20161018_234614_0658.jpg -> 10.3.100.179_01_201610182346140658_TIMING.jpg

Se isso parecer funcionar como você deseja, remova o -n.

Terdon
fonte
5

Você também pode usar o seguinte. Primeiro faça um backup dos seus arquivos e tente o seguinte:

find . -name "*.jpg" -type f -print0| while read -d $'\0' file
do
    #extension="${file##*.}"
    newfilename=$(echo "${file%.*}" | sed 's/\(.*\)_\(.*\)_/\1\2/')
    mv "$file" "$newfilename""_TIMING.jpg"
done

sed 's/\(.*\)_\(.*\)_/\1\2/')exclui os _caracteres no registro de data e hora.

Por exemplo:

user@host$ ls -lart
total 8
drwxrwxr-x 6 user user 4096 Oct 21 10:21 ..
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230014_5335.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231514_0814.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233014_5706.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234514_0896.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230114_5395.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231614_1145.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233114_6047.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234614_0547.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230114_5492.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231614_1264.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233114_6146.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234614_0658.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230214_5630.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231714_7135.jpg
drwxrwxr-x 2 user user 4096 Oct 21 10:30 .

user@host$ find . -name "*.jpg" -type f -print0 | while read -d $'\0' file
> do
>  newfilename=$(echo "${file%.*}" | sed 's/\(.*\)_\(.*\)_/\1\2/')
>  mv $file $newfilename"_TIMING.jpg"
> done

10:35:20 t $ ls -lart
total 8
drwxrwxr-x 6 user user 4096 Oct 21 10:21 ..
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182300145335_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182315140814_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182330145706_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182345140896_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182301145395_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182316141145_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182331146047_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182346140547_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182301145492_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182316141264_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182331146146_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182346140658_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182302145630_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182317147135_TIMING.jpg
drwxrwxr-x 2 user user 4096 Oct 21 10:35 .
Mustafa DOGRU
fonte
1
essa é a melhor solução. Obviamente, o soultion de Zanna é perfeito para alguns arquivos, mas como o globbing é executado pelo shell, sua solução pode falhar em um grande número de arquivos (sequência de comandos muito longa).
Rexkogitans 21/10
@rexkogitans: se você estiver em um sistema Linux moderno (ou seja, qualquer versão do Ubuntu), o limite no comprimento da linha de comando é de vários megabytes. E se houver algum problema, você pode usar find -maxdepth 1 -exec rename ... {} +para agrupar a lista do diretório atual na linha de comando da renomeação. (adicione -name *.jpgou o que quiser). Isso será executado muito mais rápido do que um loop de shell que bifurca + executivos sede mvpara cada nome de arquivo, em vez de apenas uma chamada de sistema renomeada. (Você pode se livrar da sedusando bash built-in coisas regex, mas bifurcação mvainda é lento-ish.)
Peter Cordes
2

Você provavelmente já terminou, mas aqui está uma bashsolução (simples) para todas :
"Solução simples ... do bash" é um oxímoro?

#!/bin/bash

#loop through all files ending in .jpg
for f in *.jpg;
do

    #cut out everything to the timestamp
    firsthalf=${f%_*_*_*}

    #get from the timestamp on
    lasthalf=${f#*_*_}

    #remove (all) underscores from timestamp
    #note the 2 forward slashes...
    lasthalf=${lasthalf//_/}

    #get our extension
    ext=${lasthalf##*.}

    #now we can remove the extension
    lasthalf=${lasthalf%.*}

    #rename the file
    #change `mv` to `echo` if you want to do a trial run first...
    mv "$f" "${firsthalf}_${lasthalf}_TIMING.${ext}"

done;

PS: A lógica do loop foi testada com um dos nomes de arquivos de exemplo. Passou.

J. Allan
fonte
1
Provavelmente é melhor usar um regex do bash [[ $f ~= (.*)_(.*)_(.*)_(.*)\.jpg ]]; newname=${BASH_REMATCH[1]${BASH_REMATCH:2:4}TIMING.jpgou algo assim. (totalmente testados e provavelmente errado, mas a idéia geral é que os grupos de captura de ir para a matriz BASH_REMATCH.)
Peter Cordes
@ PeterCordes: Esse é um bom ponto! Eu nunca usei ( bash) capturar grupos e, para ser sincero, o bash não é o primeiro idioma com o qual eu os experimentaria. (Eu acho que bashé uma linguagem feia.) Ainda assim, é uma boa solução e me ensinou algo muito elogio.
31116 J. Allan
Sim, a principal razão para fazer tanto processamento de texto no bash puro é ao escrever funções de preenchimento de tabulação que devem ser rápidas. Traz um novo significado à frase "código feio" ...
Peter Cordes
@ PeterCordes: Eu entendo o seu ponto, embora eu não ache esse código "feio". Pode não ser a solução de duas linhas que você forneceu, mas não é difícil de ler para mim; Além disso, ele está bem comentado ...
J. Allan
Eu estava falando sobre o código de conclusão do bash em geral ser feio (ou pelo menos difícil de ler). Na verdade, não é realmente feio, apenas um pouco alucinante (por exemplo, passar argumentos por ref no bash, passar um nome de variável e fazer com que o callee use printf -v "$3" ...para definir a variável cujo nome está dentro $3). Desmontando toda a linha de comando e colocando-a de volta juntos é muito difícil de seguir / depurar, pelo menos eu achei dessa maneira enquanto tentava limpá-lo / corrigir bugs. Veja o código no github
Peter Cordes
1

Se você pudesse usar a GUI, eu recomendaria o pyRenamer .

Está presente na maioria das distribuições, fi no Ubuntu:

sudo apt-get install pyrenamer

Pode fazer tudo o que você quiser e muito mais.

  • Pode usar padrões, adicionar ou suprimir texto.
  • Ele pode acessar os dados EXIF ​​ao renomear fotos, para que você possa gerar padrões com base na data / hora, etc.
  • Pode usar alguns metadados se renomear arquivos de música.
  • Além disso, possui uma prévia , o que pode impedir alguns erros difíceis de reverter.
jrierab
fonte
Para o downvoter ... Importa-se de explicar por que? O OP não especificou se a GUI era uma opção ou não. Vejo a maioria das respostas no modo console / script, mas muitos usuários apreciarão uma solução GUI. Ou talvez o pyRenamer tenha alguma falha que eu não conheço. De qualquer forma, gosto de saber os motivos dos votos negativos.
Jrierab # 24/16
Também posso sugerir o Thunar Bulk Renamer para uma abordagem interativa da GUI.
Tony Martin
@TonyMartin Isso deve ser um comentário em questão, isso não tem nada a ver com a resposta #
Sergiy Kolodyazhnyy
0

Aqui está o seu oneliner embutido find + xargs+ sed+ mv(love oneliners):

find . -name "*.jpg" -print0 | sort -z | xargs -0 sh -c 'for filename; do mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g"); done' sh

Explicação:

  • find . -name "*.jpg" | sort | xargs sh -c <command> sh : liste todos os JPEGs no diretório atual e execute um comando shell para cada um (a classificação é opcional, é claro, mas mantenha as coisas um pouco mais limpas se você estiver fazendo logon em algum lugar)

  • -print0, -z, -0: É bom hábito de itens separados com binário 0quando tokenizing nomes de arquivos para evitar problemas com a in-the-middle espaços em branco (não o seu caso, porém)

  • mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g");: (barras invertidas no sedregex do não ajudam a sua legibilidade, mas é simples) renomeie cada arquivo substituindo a sequência separada por sublinhado de 8 + 6 + 4 dígitos pela concatenação contígua mais essa _TIMINGcoisa ( \ié uma referência anterior ao i- grupo regex).


Refs: Xargs - homem sed

Campa
fonte