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

16

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, portanto, image1.jpg deve ser image0.jpg , image2.jpg deve ser image1.jpg e assim por diante.

Eu posso escrever um script para gerar comandos mv como esses, colocá-los em um shell script 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 simples de fazer isso no Unix. Então o que é?

    
por Wes 24.02.2014 / 21:48

6 respostas

19

A boa e antiga renomeação do perl:

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

[Comentários]

Os números das imagens devem ser maiores que 0.

Caso as imagens sejam maiores que 9 e não possuam 0s, use $(ls -v1 *) para evitar a turbulência. Proposto por @arielf e notado por @Graeme.

Em caso de dúvida, use também -v para verbose e -n para não-ação.

    
por 24.02.2014 / 22:52
6

Você pode canalizar os comandos mv gerados para bash . Então você não precisa copiá-los em um script e executá-lo. Veja:

command_that_generates_mv_commands | bash

E tudo será executado e canalizado para bash .

    
por 24.02.2014 / 21:59
5

Você pode iterar na saída ls, esta aqui funciona para o 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

    
por 24.02.2014 / 22:09
4

O seguinte parece funcionar para qualquer coisa que se ajuste ao padrão imageNUMBER.jpg . Eu coloquei echo antes do comando mv para mostrar primeiro o que o comando faria; para realmente executar a renomeação, basta remover o echo

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

Na primeira linha, o ls image*.jpg|sort -V fará com que os arquivos JPG sejam listados com números ascendentes no nome do arquivo. A linha x= extrai o número do nome do arquivo. A linha y= , em seguida, diminui o número em um. O nome do arquivo de entrada e o y number são usados no comando mv , onde o -i flag o notificará antes de sobrescrever um arquivo.

Para meu próprio 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, já que agora a ordem em que os arquivos são processados pode fazer uma grande diferença.

    
por 24.02.2014 / 22:50
4

Usando o perl script prename , que é um link simbólico para renomear as distribuições baseadas no Debian, também precisa do GNU find / sort . Os arquivos são colocados em ordem crescente para evitar sobrescrever.

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

Remova o -n quando tiver certeza de que faz o que deseja. Avisará sobre arquivos já existentes antes de fazer isso. No entanto, desde que mostre os arquivos que estão sendo renomeados em ordem crescente, não haverá conflitos quando for real.

    
por 24.02.2014 / 22:56
4

com zsh :

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

(remova -n quando feliz).

(n) é classificar a lista numericamente, então image9.jpg é renomeado antes de image10.jpg .

    
por 25.02.2014 / 21:35