¿Cambiar el nombre de varios archivos para disminuir el número en el nombre del archivo?

¿Cambiar el nombre de varios archivos para disminuir el número en el nombre del archivo?

He nombrado archivos incorrectamente que no están sincronizados con -1. El problema es que necesito cambiar el nombre de miles de ellos.

  • DBGC180_805754
  • DBGC180_805755
  • DBGC180_805756

a

  • DBGC180_805753
  • DBGC180_805754
  • DBGC180_805755

Preferiría usar scripts bash o un comando Unix.

Respuesta1

Puedes hacerlo:

# {smallestfilenum..largestfilenum}

for i in {805754..999999}; do 
   mv "DBGC180_$i" "DBGC180_$(($i-1))";
done

Pruébelo con un número pequeño (digamos 805754..805758) para asegurarse de que funcione como espera. Tenga en cuenta que si ya existe un archivo con el nuevo nombre, se sobrescribirá.

Respuesta2

  1. Mueva los archivos para cambiarles el nombre a un subdirectorio (sin cambiar su nombre).
  2. Cambie el nombre de los archivos del subdirectorio al directorio original.

Hay dos razones por las que recomiendo el paso 1, incluso si es posible prescindir de él:

  • Si el comando se interrumpe, puede continuar donde lo dejó, ya que es inmediatamente obvio qué archivos ya han sido renombrados y cuáles no.
  • No necesita preocuparse por cambiar el nombre en el orden incorrecto y sobrescribir uno de los archivos existentes.

Fragmento de shell no probado (basado en el hecho de que el número a disminuir nunca tiene ceros a la izquierda):

mkdir to_decrement
for x in DBGC180_80575[4-9] DBGC180_8057[6-9]? DBGC180_805[8-9]?? DBGC180_80[6-9]??? DBGC180_8[1-9]???? DBGC180_9?????; do
  mv "$x" to_decrement/
done
cd to_decrement
for x in *; do
  number="${x##*_}"
  mv -i -- "$x" "../${x%_*}_$((number-1))"
done
cd ..
rmdir to_decrement

Conzsh, puedes hacer esto mucho más simple, gracias a suglobo de rango numérico, esincorporadomvlo que evita encontrarse con límites de longitud de línea de comando, y sufunción de cambio de nombre masivo basada en patrones. En zsh:

autoload -U zmv
zmodload -m -F zsh/files b:zf_\*
mkdir to_decrement
zf_mv DBGC180_<805754-> to_decrement/
zmv 'to_decrement/(*)_(*)' '${1}_$(($2-1))'
rmdir to_decrement

Respuesta3

Entonces, desea cambiar el nombre DBGC180_805754a DBGC180_805753, ...55a ...54, etc. Ese es el problema que abordaré.

Primero, coloque este script en algún lugar de su PATH, llámelo waltinator.

#!/bin/bash
#step through the parameters 
while [[ -n "$1" ]] ; do
    oldname="$1"
    # shift the arguments left
    shift;
    # strip off the fixed part of the old name
    oldnum=${oldname##DBGC180_}
    # decrement the number (this is what was wanted, right?)
    newnum=$(( $oldnum - 1 ))
    # build the new, improved filename
    newname="DBGC180_$newnum"
    if [[ -f "$newname" ]] ; then
        printf "Cannot rename $oldname to $newname, $newname exists.\n" >&2
        exit 1
    fi
    mv --no-clobber "$oldname" "$newname"
done
exit 0

Para el siguiente paso, suponga que el script está en $HOME/bin/waltinator, y usted tiene en chmod +x $HOME/bin/waltinator.

find . -type f -name 'BDGC180_[0-9][0-9][0-9][0-9][0-9][0-9]` -print | \
    sort | \
    xargs $HOME/bin/waltinator

Los findarchivos de búsqueda (sin ningún orden en particular), cuyos nombres coinciden con el patrón global del shell " BDGC180_seguido de 6 dígitos ( [0-9]). Como queremos una lista ordenada (sería un error cambiar el nombre ...97antes ...96de cambiar el nombre ...96), ejecutamos la salida de findtravés de sort. Luego usamos xargspara tomar la lista (ordenada) de nombres de archivos y crear un comando para pasar la lista (ordenada) de nombres de archivos a $HOME/bin/waltinatorRead man xargssi necesita acortar la lista de argumentos.

Para el caso lea:

for page in bash mv find sort xargs ; do
    man "$page"
done   

Respuesta4

Úselo renamepara sustituir cada número por sí mismo menos 1.

$ rename -v 's/\d{6}/sprintf("%06",($&-1))/e'    

Notas

  • renameutiliza expresiones Perl para cambiar el nombre de los archivos.
  • sespecifica que renamesustituirá algunos o todos los nombres de archivos que coincidan con el patrón de expresión regular.
  • Las expresiones de sustitución de Perl están estructuradas como tales.
    • s/PATTERN/REPLACEMENT/MODIFIER
  • \d{6}es el patrón que renamebuscará y sustituirá. Son 6 dígitos decimales.
  • $es la variable que almacena la subcadena que coincidió \d{6}(en este caso la "subcadena" es un int).
  • sprintf("%06",($&-1))recupera el valor almacenado en $, lo disminuye y luego devuelve este valor como reemplazo. Está %06ahí para manejar los ceros a la izquierda.
  • eespecificado que renameevalúa el reemplazo como si fuera una declaración Perl y utiliza su valor de retorno como texto de reemplazo.
  • -vhace renameeco de lo que está haciendo.

Si quieres estar más seguro, usa la bandera -npara que renamesolo te diga lo que haría en lugar de hacerlo.

Esto parece funcionar sólo para decrementar, así que manéjelo con cuidado.

información relacionada