Subtraia 1 de todos os nomes de arquivos (renomeie-os) em um diretório.


17

Eu tenho um diretório que contém arquivos de imagem com nomes como

image1.jpg 
image2.jpg 
image3.jpg
...

Infelizmente, os nomes das imagens devem ser baseados em zero, como image1.jpgdeveriam image0.jpg, image2.jpgdevem ser image1.jpge assim por diante.

Posso escrever um script para gerar comandos mv como esses, colocá-los em um script shell e depois executá-los -

mv image1.jpg image0.jpg
mv image2.jpg image1.jpg
mv image3.jpg image2.jpg
...

Mas suponho que exista uma maneira mais clara de fazer isso no Unix. Então o que é?


6
Essa é realmente a maneira mais simples de fazer isso, desde que não haja lacunas. ( for i in $(seq 0 100); do mv image$[i+1].jpg image$i.jpg; done)
Ricky Beam

5
A ordem das imagens é importante? Caso contrário, apenas renomeie a última imagem de imageN.jpgpara image0.jpge pronto.
Jnovacho

@jnovacho, bastante inteligente! Mas sim, a ordem das imagens é importante.
25414 Wes Wes

Respostas:


20

O bom e velho perl renomear:

rename 's/(\d+)(\.jpg)/($1-1).$2/e' *

[Observações]

Os números da imagem devem ser maiores que 0.

Caso as imagens sejam maiores que 9 e não tenham 0s à esquerda, use $(ls -v1 *)para evitar estroboscópios. Proposta por @arielf e notada por @Graeme.

Em caso de dúvida, use também -vpara verboso e -nsem ação.


O que indica o "e"?
24414 Wes Wes

3
'e' significa avaliar, a seção de substituição será avaliada. Veja tambémperlreref

6
Os arquivos devem ser transmitidos em ordem crescente, para evitar obstruções. Isso funcionará bem apenas se houver menos de 10 arquivos (ou se os números tiverem zeros à esquerda).
Graeme

Eu já notei isso, também não deve haver um 0nas fontes.

2
substitua o *no final por `ls -v1 *`e você estará mais seguro de bater. Vai do número mais baixo para o mais alto.
Arielf 03/03

6

Você pode canalizar os mvcomandos gerados para bash. Portanto, você não precisa copiá-los em um script e executá-lo. Vejo:

command_that_generates_mv_commands | bash

E tudo será executado conforme o canal bash.


Isso não é mais arrumado. :)Resolve o problema, então +1.
JMCF125

5

Você pode iterar na saída ls, esta funciona no seu exemplo:

i=0 
for file in $(ls *.jpg | sort) ; do 
     mv $file $(echo $file | sed 's/[0-9]*.jpg$/'${i}'.jpg/')
     i=$((++i))
done

Você deve estar no mesmo caminho dos seus arquivos


1
Melhor usar -iou -ncom mv, evitará a substituição em casos extremos.
Graeme

não sort -Vseria melhor?
user80551

sortnão funcionará, será exibido image10.jpgantes do image1.jpgque pode ser um problema. Você precisa sort -nk 1.8como na resposta de @ Graeme.
terdon

@ user80551, sort -Vé uma boa ideia, irá adicioná-lo à minha resposta. Porém, pode haver outros casos extremos, apenas bons conselhos para adicionar esse tipo de opções com perguntas como essa, caso alguém copie e acabe causando algum dano.
Graeme

4

A seguir, parece funcionar para qualquer coisa que se encaixe no padrão imageNUMBER.jpg. Coloquei echoantes do mvcomando para mostrar primeiro o que o comando faria; para realmente executar a renomeação, basta remover oecho

for i in `ls image*.jpg|sort -V` ; do 
    x=`echo $i|sed -e "s/image\(.*\).jpg/\1/"`
    y=$(( $x - 1 ))
    echo mv -i $i image$y.jpg
done

Na primeira linha, isso ls image*.jpg|sort -Vfará com que os arquivos JPG sejam listados com números crescentes no nome do arquivo. A x=linha extrai o número do nome do arquivo. A y=linha então diminui o número em um. O nome do arquivo de entrada e o ynúmero são usados ​​no mvcomando, onde o -isinalizador notificará você antes de substituir um arquivo.

Para meu pequeno teste, isso produziu a saída:

mv -i image1.jpg image0.jpg
mv -i image2.jpg image1.jpg
mv -i image123.jpg image122.jpg

Pessoalmente, sugiro renomear para um nome de arquivo mais diferente, pois agora a ordem na qual os arquivos são processados ​​pode fazer uma grande diferença.


1
Melhor usar -iou -ncom mv, evitará a substituição em casos extremos.
Graeme

Muito boa sugestão, eu vou editar a resposta
brm

No macOS, você deve usar sort -n, a -Vopção não existe.
Vincent Sit

4

O uso do perlscript prename, que tem o link simbólico para renomear nas distribuições baseadas no Debian, também precisa do GNU find/ sort. Os arquivos são colocados em ordem crescente para evitar qualquer substituição.

find . -regex '\./image[0-9]+\.jpg' -print0 | sort -zV |
  xargs -0 rename -n 's/(\d+)\.jpg$/@{[$1-1]}.jpg/'

Remova a -nvez que tiver certeza de que faz o que deseja. Irá avisar sobre arquivos já existentes antes de fazê-lo. No entanto, desde que mostre os arquivos sendo renomeados em ordem crescente, não haverá conflitos quando executados de verdade.


O arquivo já existe problemas com este.
24414 Wes Wes

4

Com zsh:

autoload zmv # (in ~/.zshrc)
zmv -Qf -n 'image(<->).jpg(n)' 'image$(($1-1)).jpg'

(remova -nquando estiver feliz).

(n)é classificar a lista numericamente e image9.jpgrenomear antes image10.jpg.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.