Resta 1 de todos los nombres de archivo (renómbralos) en un directorio.

17

Tengo un directorio que contiene archivos de imagen con nombres como

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

Desafortunadamente, los nombres de las imágenes deben estar basados ​​en cero, por lo que image1.jpgdeberían ser image0.jpg, image2.jpgdeberían ser, image1.jpgetc.

Puedo escribir un script para generar comandos mv como estos, ponerlos en un script de shell y luego ejecutarlos:

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

Pero supongo que hay una forma más ordenada de hacerlo en Unix. ¿Así que qué es lo?

Wes
fuente
66
En realidad, esa es la forma más sencilla de hacerlo, siempre que no haya brechas. ( for i in $(seq 0 100); do mv image$[i+1].jpg image$i.jpg; done)
Ricky Beam
55
¿Es importante el orden de las imágenes? Si no, simplemente cambie el nombre de la última imagen de imageN.jpga image0.jpgy ya está.
jnovacho
@jnovacho, ¡bastante listo! Pero sí, el orden de las imágenes es importante.
Wes

Respuestas:

20

El buen viejo perl renombrar:

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

[Observaciones]

Los números de imagen deben ser mayores que 0.

En caso de que las imágenes sean mayores que 9 y no tengan ceros a la izquierda, use $(ls -v1 *)para evitar el golpeteo. Propuesto por @arielf y notado por @Graeme.

En caso de duda, utilice también -vpara verbose y -nno-action.


fuente
¿Qué indica la "e"?
Wes
3
'e' significa evaluar, se evaluará la sección de reemplazo. vea tambiénperlreref
66
Los archivos deben pasarse en orden ascendente para evitar cualquier golpe. Esto funcionará bien solo si hay menos de 10 archivos (o si los números tienen ceros a la izquierda).
Graeme
Ya me di cuenta de esto, tampoco debe haber una 0en las fuentes.
2
reemplace el *al final con `ls -v1 *`y estará más seguro de golpear. Irá del número más bajo al más alto.
arielf
6

Puede canalizar los mvcomandos generados a bash. Por lo tanto, no tiene que copiarlos en un script y ejecutarlos. Ver:

command_that_generates_mv_commands | bash

Y se ejecutará todo lo que se canaliza bash.

caos
fuente
Eso no es más ordenado. :)Sin embargo, resuelve el problema, entonces +1.
JMCF125
5

Puede iterar en la salida de ls, este funciona para su ejemplo:

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

Debes estar en la misma ruta de tus archivos

babasbot
fuente
1
Mejor usar -io -ncon mv, evitará sobrescribir en casos extremos.
Graeme
no sort -Vsería mejor en su lugar?
user80551
sortno funcionará, se mostrará image10.jpgantes, lo image1.jpgque podría ser un problema. Necesitas sort -nk 1.8como en la respuesta de @ Graeme.
terdon
@ user80551, sort -Ves una buena idea, lo agregaré a mi respuesta. Sin embargo, podría haber otros casos extremos, solo un buen consejo para agregar este tipo de opciones con preguntas como esta en caso de que alguien copie y termine haciendo algún daño.
Graeme
4

Lo siguiente parece funcionar para cualquier cosa que se ajuste al patrón imageNUMBER.jpg. He colocado echoantes del mvcomando para mostrar primero lo que haría el comando; para realizar el cambio de nombre, simplemente elimine elecho

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

En la primera línea, ls image*.jpg|sort -Vhará que los archivos JPG se enumeren con números ascendentes en el nombre del archivo. La x=línea extrae el número del nombre del archivo. La y=línea luego disminuye el número en uno. El nombre de archivo de entrada y el ynúmero se utilizan en el mvcomando, donde la -ibandera le notificará antes de sobrescribir un archivo.

Para mi pequeña prueba, esto produjo el resultado:

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

Personalmente, sugiero cambiar el nombre a un nombre de archivo más diferente, ya que ahora el orden en que se procesan los archivos puede marcar una gran diferencia.

brm
fuente
1
Mejor usar -io -ncon mv, evitará sobrescribir en casos extremos.
Graeme
Muy buena sugerencia, editaré la respuesta
brm
En macOS, debe usar sort -n, la -Vopción no existe.
Vincent Sit
4

El uso del perlscript prename, que está vinculado para cambiar el nombre de las distribuciones basadas en Debian, también necesita GNU find/ sort. Los archivos se colocan en orden ascendente para evitar sobrescribirlos.

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

Quítelo -nuna vez que esté seguro de que hace lo que quiere. Advertirá sobre los archivos ya existentes antes de hacerlo. Sin embargo, siempre que muestre que los archivos se renombran en orden ascendente, no habrá conflictos cuando se ejecuten de verdad.

Graeme
fuente
El archivo ya existe problemas con este.
Wes
4

Con zsh:

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

(eliminar -ncuando sea feliz).

(n)es ordenar la lista numéricamente para que image9.jpgse renombre antes image10.jpg.

Stéphane Chazelas
fuente