Digamos que tengo una variedad de archivos llamados: "bla-10-bla", "bla-11-bla", etc. hasta "bla-30-bla".
Me gustaría cambiar los nombres a "bla-20-bla", "bla-21-bla", etc... hasta "bla-40-bla".
¿Hay alguna forma de hacer esto en la terminal?
Respuesta1
Tu puedes hacer:
#!/bin/bash
files=( blah-??-blah )
for ((i=${#files[@]}-1; i>=0; i--)); do
first="${files[$i]%%-*}"
num="$(grep -o '[0-9]\+' <<<"${files[$i]}")"
last="${files##*-}"
echo mv "$first-$num-$last" "$first-$((num+10))-$last"
done
Si está satisfecho con todo, agregue | bash
al final para que mv
se realice la operación.
Hemos puesto los nombres de archivos relevantes en una matriz.
files
Luego hemos iterado sobre los elementos de la matriz desde el final, es decir, del último al primero.
first
tendrá la primera parte del nombre del archivo, es decir, la parte anterior a la primera-
last
tendrá la última parte del nombre del archivo, es decir, la parte después del último-
num
tendrá el número entre dos-
mv "$first-$num-$last" "$first-$((num+10))-$last"
hará la operación de cambio de nombre en consecuencia
Ejemplo:
$ ls -1
blah-10-blah
blah-11-blah
blah-12-blah
blah-13-blah
blah-14-blah
blah-15-blah
blah-16-blah
blah-17-blah
blah-18-blah
blah-19-blah
blah-20-blah
blah-21-blah
blah-22-blah
blah-23-blah
blah-24-blah
blah-25-blah
blah-26-blah
blah-27-blah
blah-28-blah
blah-29-blah
blah-30-blah
blah-foo-1
blah-foo-2
$ for ((i=${#files[@]}-1; i>=0; i--)); do first="${files[$i]%%-*}" \
num="$(grep -o '[0-9]\+' <<<"${files[$i]}")" last="${files##*-}"; \
echo mv "$first-$num-$last" "$first-$((num+10))-$last"; done
mv blah-30-blah blah-40-blah
mv blah-29-blah blah-39-blah
mv blah-28-blah blah-38-blah
mv blah-27-blah blah-37-blah
mv blah-26-blah blah-36-blah
mv blah-25-blah blah-35-blah
mv blah-24-blah blah-34-blah
mv blah-23-blah blah-33-blah
mv blah-22-blah blah-32-blah
mv blah-21-blah blah-31-blah
mv blah-20-blah blah-30-blah
mv blah-19-blah blah-29-blah
mv blah-18-blah blah-28-blah
mv blah-17-blah blah-27-blah
mv blah-16-blah blah-26-blah
mv blah-15-blah blah-25-blah
mv blah-14-blah blah-24-blah
mv blah-13-blah blah-23-blah
mv blah-12-blah blah-22-blah
mv blah-11-blah blah-21-blah
mv blah-10-blah blah-20-blah
$ for ((i=${#files[@]}-1; i>=0; i--)); do first="${files[$i]%%-*}" \
num="$(grep -o '[0-9]\+' <<<"${files[$i]}")" last="${files##*-}";\
echo mv "$first-$num-$last" "$first-$((num+10))-$last"; done | bash
$ ls -1
blah-20-blah
blah-21-blah
blah-22-blah
blah-23-blah
blah-24-blah
blah-25-blah
blah-26-blah
blah-27-blah
blah-28-blah
blah-29-blah
blah-30-blah
blah-31-blah
blah-32-blah
blah-33-blah
blah-34-blah
blah-35-blah
blah-36-blah
blah-37-blah
blah-38-blah
blah-39-blah
blah-40-blah
blah-foo-1
blah-foo-2
Respuesta2
Es importante procesar los archivos en orden numérico inverso; de lo contrario, la tarea fallará debido a que ya existen archivos con el nombre de archivo de destino:
find . -maxdepth 1 -type f -name 'blah-??-blah' -print0 | sort -zr | xargs -0 rename 's/-\K([0-9]{2})/$1+10/e'
find . -maxdepth 1 -type f -name 'blah-??-blah' -print0
: imprime una lista separada por NULL de los archivos en el directorio de trabajo actual que coinciden con el patrón globalblah-??-blah
;sort -zr
: ordena la lista en orden numérico inverso;xargs -0 rename 's/-\K([0-9]{2})/$1+10/e'
: cambia el nombre de los archivos sustituyendo los primeros dígitos después de un guión con el valor correspondiente incrementado en 10;
% tree
.
├── blah-10-blah
├── blah-11-blah
├── blah-12-blah
├── blah-13-blah
├── blah-14-blah
├── blah-15-blah
├── blah-16-blah
├── blah-17-blah
├── blah-18-blah
├── blah-19-blah
├── blah-20-blah
├── blah-21-blah
├── blah-22-blah
├── blah-23-blah
├── blah-24-blah
├── blah-25-blah
├── blah-26-blah
├── blah-27-blah
├── blah-28-blah
├── blah-29-blah
└── blah-30-blah
0 directories, 21 files
% find . -maxdepth 1 -type f -name 'blah-??-blah' -print0 | sort -zr | xargs -0 rename 's/-\K([0-9]{2})/$1+10/e'
% tree
.
├── blah-20-blah
├── blah-21-blah
├── blah-22-blah
├── blah-23-blah
├── blah-24-blah
├── blah-25-blah
├── blah-26-blah
├── blah-27-blah
├── blah-28-blah
├── blah-29-blah
├── blah-30-blah
├── blah-31-blah
├── blah-32-blah
├── blah-33-blah
├── blah-34-blah
├── blah-35-blah
├── blah-36-blah
├── blah-37-blah
├── blah-38-blah
├── blah-39-blah
└── blah-40-blah
0 directories, 21 files
Si usa Zsh, la tarea se puede simplificar enormemente, ya que Zsh permite expandir los nombres de archivos en orden numérico inverso:
rename 's/-\K([0-9]{2})/$1+10/e' blah-??-blah(On)
% tree
.
├── blah-10-blah
├── blah-11-blah
├── blah-12-blah
├── blah-13-blah
├── blah-14-blah
├── blah-15-blah
├── blah-16-blah
├── blah-17-blah
├── blah-18-blah
├── blah-19-blah
├── blah-20-blah
├── blah-21-blah
├── blah-22-blah
├── blah-23-blah
├── blah-24-blah
├── blah-25-blah
├── blah-26-blah
├── blah-27-blah
├── blah-28-blah
├── blah-29-blah
└── blah-30-blah
0 directories, 21 files
% rename 's/-\K([0-9]{2})/$1+10/e' blah-??-blah(On)
% tree
.
├── blah-20-blah
├── blah-21-blah
├── blah-22-blah
├── blah-23-blah
├── blah-24-blah
├── blah-25-blah
├── blah-26-blah
├── blah-27-blah
├── blah-28-blah
├── blah-29-blah
├── blah-30-blah
├── blah-31-blah
├── blah-32-blah
├── blah-33-blah
├── blah-34-blah
├── blah-35-blah
├── blah-36-blah
├── blah-37-blah
├── blah-38-blah
├── blah-39-blah
└── blah-40-blah
0 directories, 21 files
Respuesta3
La idea básica de este enfoque es colocar todos los archivos en el directorio "cesta" temporal y luego seleccionarlos uno por uno, crear un nuevo nombre y regresar con el nuevo nombre al directorio original.
El siguiente script toma un solo argumento ( $1 ), que es el directorio donde se encuentran los archivos cuyo nombre desea cambiar.
Manifestación
xieerqi:$ ls testdir
blah-10-blah blah-20-blah blah-30-blah blah-40-blah
xieerqi:$ cat testdir/*
I am file 10
I am file 20
I am file 30
I am file 40
xieerqi:$ ./incrementNames.sh testdir
blah-10-blah ../blah-20-blah
blah-20-blah ../blah-30-blah
blah-30-blah ../blah-40-blah
blah-40-blah ../blah-50-blah
xieerqi:$ ls testdir
blah-20-blah blah-30-blah blah-40-blah blah-50-blah TMP/
xieerqi:$ cat testdir/blah
blah-20-blah blah-30-blah blah-40-blah blah-50-blah
xieerqi:$ cat testdir/blah-20-blah
I am file 10
xieerqi:$ cat testdir/blah-30-blah
I am file 20
Guion
#!/bin/bash
if [ "$#" -ne 1 ]; then
echo "Usage: incrementNames.sh /path/to/dir" && exit
fi
# navigate to target directory
# create temporary directory
cd "$1"
mkdir TMP
# move everything to TMP directory
find . -maxdepth 1 -type f -iname "*-*" -exec mv -t TMP {} \+
# drop down to TMP directory pick filesback into the directory , and rename them as we go
cd TMP
find . -maxdepth 1 -type f -iname "*-*" -printf "%f\n" | sort | while IFS= read FILENAME
do
NEW="$( awk -F '-' '{print $1FS$2+10FS$3 }' <<< "$FILENAME")"
echo "$FILENAME" "../$NEW"
mv "$FILENAME" ../"$NEW"
done
Limitación
Este script es específicamente para archivos que siguen un patrón text-number-text
, o al menos text-number
un patrón. No funcionará para otros