Cambiar el nombre de archivos a granel

25

Tengo varios archivos:

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

Quiero cambiar el nombre con 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

Necesita eliminar la _marca de tiempo en y agregar el _TIMING.

Jojo Mendoza
fuente
55
Utilice ejemplos consistentes en sus preguntas. Parece que desea reemplazar 10.3.100.179con 10.4.100.135. ¿Es eso lo que quieres o simplemente quieres eliminar el _TIMINGy _el tiempo?
terdon
3
Un buen momento para recordarle a la gente que existe un estándar iso8601 para las fechas (que funcionan tanto para los nombres de archivo como para las entradas de registro) ^^ Entonces, tal vez debería reconsiderar el cambio de nombre para que sea: AAAA-MM-DDThh: mm: ss.mmm (ex : su primer archivo se convertiría en: 10.4.100.135_01_2016-10-13T13:11:08.389_TIMING.jpg(y "TIMING" podría incluso eliminarse, ya que ahora se ve claramente como una fecha y hora (y milisegundos), especialmente cuando el estándar se generaliza. El T es parte del estándar y yo creció a gustar (y llevarlo a cabo se rompe la norma ^^)
Olivier Dulac
@ OlivierDulac No recomendaría usar :en un nombre de archivo. Creo que Windows no lo admite.
Justin
@Justin buen punto. el estándar recomienda soltarlo para los nombres de archivo. Di la versión en el archivo
Olivier Dulac

Respuestas:

38

Instalar renameutilsy usar qmvcon su editor de texto favorito.

qmvcarga todos los nombres en su editor y cuando guarda y cierra aplica sus cambios a los archivos reales. Si los cambios son inconsistentes (p. Ej., Dos archivos tienen el mismo nombre), abortará sin tocar nada. También maneja los nombres circulares correctamente.

Yo suelo hacer:

$ qmv -f do

para que muestre solo una columna de nombres (hacer: solo destino). Así es como se ve:

qmw

Si lo combina con los múltiples cursores de SublimeText, Atom o Visual Studio Code, es una herramienta muy agradable y poderosa para renombrar en masa. Por ejemplo, para Atom, lo harías EDITOR="atom -w" qmv -f do.

ateijelo
fuente
1
Bienvenido a askUbuntu! ¡Esto es genial!
αғsнιη
Firmado solo a +! eso. ;)
J. Allan
2
Wow, buena herramienta y buena animación GIF. Gran primera respuesta, ¡bienvenido! :)
Byte Commander
1
Gracias @KasiyA por incluir la imagen y gracias a todos por los comentarios positivos.
ateijelo
1
@kasperd Sí, advertirá que el plan de cambio de nombre contiene errores y abrirá una consola interactiva donde se pueden tomar más medidas.
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/' *

Con -nesto saldrá lo que va a hacer sin hacer ningún cambio:

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)

Si se ve bien, quite el -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/ buscar y reemplazar
  • ^ el comienzo del nombre (anclaje)
  • [0-9] cualquier número
  • + uno o más de los caracteres anteriores
  • \.literal .(sin \esto coincide con ningún carácter)
  • () para mantener esta parte
  • $1$2$3$3 referencias a las cosas que coincidieron anteriormente y se mantuvieron con ()

Nota: *al final del comando coincide todos los archivos visibles en el directorio actual. Use un globo más adecuado si es necesario.

Zanna
fuente
2
En algunas distribuciones, este comando está disponible como prename(p para perl, porque el primer argumento es una expresión perl)
Peter Cordes
12

mmv puede hacerlo de la siguiente manera:

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, ... hace referencia a cada uno de ellos con el '*' correspondiente aquí.

Es aún más corto con:

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

Otro renameenfoque:

$ 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

Si eso parece funcionar como lo desea, elimine el -n.

terdon
fuente
5

También puedes usar lo siguiente. Primero haga una copia de seguridad de sus archivos e intente esto:

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/')elimina los _caracteres en la marca de tiempo.

Por ejemplo:

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
fuente
1
Esta es la mejor solución. Por supuesto, el alma de Zanna es perfecta para un par de archivos, pero dado que el shell realiza el bloqueo, su solución puede fallar en una gran cantidad de archivos (cadena de comando demasiado larga).
rexkogitans
@rexkogitans: si está en un sistema Linux moderno (es decir, cualquier versión de Ubuntu), el límite en la longitud de la línea de comandos es de varios megabytes. Y si es un problema, puede usar find -maxdepth 1 -exec rename ... {} +para agrupar la lista del directorio actual en la línea de comando de renombrar. (agregue -name *.jpgo lo que quiera). Eso se ejecutará mucho más rápido que un bucle de shell que bifurca + ejecutivos sedy mvpara cada nombre de archivo, en lugar de solo una llamada de cambio de nombre del sistema. (Podrías deshacerte del seduso de las expresiones regulares incorporadas de bash, pero la bifurcación mvsigue siendo lenta).
Peter Cordes
2

Probablemente haya terminado, pero aquí hay una bashsolución (simple) :
¿Es "simple ... solución bash" un oxímoron?

#!/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;

PD: La lógica en el bucle se probó con uno de sus nombres de archivo de ejemplo. Pasó.

J. Allan
fuente
1
Probablemente sea mejor usar un bash regex con [[ $f ~= (.*)_(.*)_(.*)_(.*)\.jpg ]]; newname=${BASH_REMATCH[1]${BASH_REMATCH:2:4}TIMING.jpgo algo así. (totalmente no probado y probablemente equivocado, pero la idea general es que los grupos de captura entren en la matriz BASH_REMATCH).
Peter Cordes
@PeterCordes: ¡Ese es un buen punto! Nunca he usado ( bash) grupos de captura, y para ser sincero, bash no es el primer idioma con el que los probaría. (Creo que bashes un lenguaje feo). Aún así, es una buena solución y me enseñó algo muy bueno.
J. Allan
Sí, la razón principal para hacer tanto procesamiento de texto en bash puro es cuando se escriben funciones de finalización de tabulación que deberían ser rápidas. Aporta un significado completamente nuevo a la frase "código feo" ...
Peter Cordes
@PeterCordes: Recibo su punto, aunque yo no creo que el código es "feo". Puede que no sea la solución de 2 líneas que proporcionó, pero no es difícil de leer en lo que a mí respecta; además está bien comentado ...
J. Allan
Estaba hablando de que el código de finalización de bash en general es feo (o al menos difícil de leer). En realidad no es realmente feo, solo algo alucinante (por ejemplo, pasar argumentos por ref en bash hecho pasando un nombre de variable y haciendo que la persona que llama use printf -v "$3" ...para establecer la variable cuyo nombre está en $3). Desmontando toda la línea de comando y volviendo a colocarla juntos es bastante difícil de seguir / depurar, al menos lo encontré de esa manera al tratar de limpiarlo / corregir errores. Ver el código en github
Peter Cordes
1

Si pudiera usar GUI, recomendaría pyRenamer .

Está presente en la mayoría de las distribuciones, fi en Ubuntu:

sudo apt-get install pyrenamer

Puede hacer todo lo que quieras y más.

  • Puede usar patrones, agregar o suprimir texto.
  • Puede acceder a los datos EXIF ​​si cambia el nombre de las fotos, por lo que puede generar patrones basados ​​en la fecha / hora, etc.
  • Puede usar algunos metadatos si cambia el nombre de los archivos de música.
  • Además, tiene una vista previa , que puede evitar algunos errores difíciles de revertir.
jrierab
fuente
Para el votante ... ¿Te importaría explicar por qué? OP no especificó si GUI era una opción o no. Veo que la mayoría de las respuestas se dirigen a la consola / script, pero muchos usuarios apreciarán una solución GUI. O tal vez pyRenamer tiene algún defecto que no conozco. En cualquier caso, me gusta saber los motivos de los votos negativos.
jrierab
¿Puedo sugerir también Thunar Bulk Renamer para un enfoque rápido e interactivo de GUI?
Tony Martin
@TonyMartin Esto debería ser un comentario en cuestión, esto no tiene nada que ver con la respuesta
Sergiy Kolodyazhnyy
0

Aquí está su oneliner incorporado crudo 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

Explicación:

  • find . -name "*.jpg" | sort | xargs sh -c <command> sh : enumere todos los archivos JPEG en el directorio actual y luego ejecute un comando de shell para cada uno (la clasificación es opcional, por supuesto, pero mantenga las cosas un poco más limpias si está iniciando sesión en algún lugar)

  • -print0, -z, -0: Es buena costumbre de elementos separados con binario 0cuando tokenizar nombres de archivo para evitar problemas con la in-the-middle espacios en blanco (no es su caso, sin embargo)

  • mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g");: (las barras invertidas en la sedexpresión regular de 's no ayudan a su legibilidad, pero es simple) cambie el nombre de cada archivo reemplazando la secuencia separada por guiones bajos de 8 + 6 + 4 dígitos con su concatenación contigua más esta _TIMINGcosa ( \ies una referencia a la i- th regex group).


Refs: Xargs - hombre sed

Campa
fuente