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
- Mueva los archivos para cambiarles el nombre a un subdirectorio (sin cambiar su nombre).
- 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, esincorporadomv
lo 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_805754
a DBGC180_805753
, ...55
a ...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 find
archivos 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 ...97
antes ...96
de cambiar el nombre ...96
), ejecutamos la salida de find
través de sort
. Luego usamos xargs
para tomar la lista (ordenada) de nombres de archivos y crear un comando para pasar la lista (ordenada) de nombres de archivos a $HOME/bin/waltinator
Read man xargs
si necesita acortar la lista de argumentos.
Para el caso lea:
for page in bash mv find sort xargs ; do
man "$page"
done
Respuesta4
Úselo rename
para sustituir cada número por sí mismo menos 1.
$ rename -v 's/\d{6}/sprintf("%06",($&-1))/e'
Notas
rename
utiliza expresiones Perl para cambiar el nombre de los archivos.s
especifica querename
sustituirá 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 querename
buscará 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á%06
ahí para manejar los ceros a la izquierda.e
especificado querename
evalúa el reemplazo como si fuera una declaración Perl y utiliza su valor de retorno como texto de reemplazo.-v
hacerename
eco de lo que está haciendo.
Si quieres estar más seguro, usa la bandera -n
para que rename
solo te diga lo que haría en lugar de hacerlo.
Esto parece funcionar sólo para decrementar, así que manéjelo con cuidado.