
Tengo un directorio que contiene subdirectorios que contienen muchos archivos llamados como:
file1.tif
file2.tif
file3.tif
file4.tif
file5.tif
file6.tif
file7.tif...
Quiero agregar un sufijo "cíclico" c1
y para obtener los nombres de los archivos c2
:c3
file1c1.tif
file2c2.tif
file3c3.tif
file4c1.tif
file5c2.tif
file6c3.tif
file7c1.tif...
Y esto en todos los subdirectorios del directorio superior.
Pero no puedo encontrar cómo hacerlo.
¿Es eso posible? ¿Cómo?
Respuesta1
Con find
+ el basado en Perl prename
(también conocido como rename
en algunos Ubuntus anteriores), puede hacer coincidir la secuencia de dígitos antes de un literal .
y luego escribirlo en el formato deseado usando la división de módulo, por ejemplo.
find . -name '*.tif' -execdir prename -vn -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +
(Las -vn
banderas le permiten hacer un 'ensayo' para ver cómo se cambiaría el nombre de los archivos antes de confirmarlos).
Ex. dado
$ tree
.
├── bar
│ ├── file1.tif
│ ├── file2.tif
│ ├── file3.tif
│ ├── file4.tif
│ ├── file5.tif
│ ├── file6.tif
│ └── file7.tif
├── foo
│ ├── egg
│ │ ├── file1.tif
│ │ └── file2.tif
│ ├── file1.tif
│ ├── file2.tif
│ └── file3.tif
└── spam
├── file1.tif
└── file2.tif
4 directories, 14 files
Entonces
find . -name '*.tif' -execdir prename -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +
resultados en
$ tree
.
├── bar
│ ├── file1c1.tif
│ ├── file2c2.tif
│ ├── file3c3.tif
│ ├── file4c1.tif
│ ├── file5c2.tif
│ ├── file6c3.tif
│ └── file7c1.tif
├── foo
│ ├── egg
│ │ ├── file1c1.tif
│ │ └── file2c2.tif
│ ├── file1c1.tif
│ ├── file2c2.tif
│ └── file3c3.tif
└── spam
├── file1c1.tif
└── file2c2.tif
4 directories, 14 files
Respuesta2
Editar según el comentario:
Si desea realizar un ciclo del contador, es decir, <number>
para c<number>
realizar un ciclo entre 1 y 3:
Ejecución en seco:
shopt -s globstar
for d in **/*/; do
( cd "$d" && pwd && count=1 && shopt -s nullglob && for f in file*.tif; do
echo mv -i "$f" "${f%.tif}"c${count}.tif
if ((count=3)); then
count=1
else
((count++))
fi
done )
done
Acción:
shopt -s globstar
for d in **/*/; do
( cd "$d" && count=1 && shopt -s nullglob && for f in file*.tif; do
mv -i "$f" "${f%.tif}"c${count}.tif
if ((count=3)); then
count=1
else
((count++))
fi
done )
done
Ejemplo:
$ tree
.
├── bar
│ ├── file1.tif
│ ├── file2.tif
│ ├── file3.tif
│ └── file4.tif
├── foo
│ ├── egg
│ │ ├── file1.tif
│ │ └── file2.tif
│ ├── file1.tif
│ ├── file2.tif
│ └── file3.tif
└── spam
├── file1.tif
└── file2.tif
$ shopt -s globstar
$ for d in **/*/; do ( cd "$d" && pwd && count=1 && shopt -s nullglob && for f in file*.tif; do \
echo mv -i "$f" "${f%.tif}"c${count}.tif; if ((count=3)); then count=1; else ((count++)); fi; done ); done
/home/foobar/bar
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
mv -i file3.tif file3c3.tif
mv -i file4.tif file4c1.tif
/home/foobar/foo
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
mv -i file3.tif file3c3.tif
/home/foobar/foo/egg
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
/home/foobar/spam
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
$ for d in **/*/; do ( cd "$d" && count=1 && shopt -s nullglob && for f in file*.tif; do \
mv -i "$f" "${f%.tif}"c${count}.tif; if ((count=3)); then count=1; else ((count++)); fi; done ); done
$ tree
.
├── bar
│ ├── file1c1.tif
│ ├── file2c2.tif
│ ├── file3c3.tif
│ └── file4c1.tif
├── foo
│ ├── egg
│ │ ├── file1c1.tif
│ │ └── file2c2.tif
│ ├── file1c1.tif
│ ├── file2c2.tif
│ └── file3c3.tif
└── spam
├── file1c1.tif
└── file2c2.tif
Respuesta original:
Con bash
:
shopt -s globstar
for d in **/*/; do ( cd "$d" && pwd && count=1 && shopt -s nullglob \
&& for f in file*.tif; do echo mv -i "$f" "${f%.tif}"c${count}.tif; \
((count++)); done ); done
Aquí estamos recorriendo los nombres de los directorios,
globstar
la opción de shell nos permite recorrer el directorio de forma recursiva.La parte interna
()
se ejecuta en un subshell, esto es para evitar quecd
se modifique en el shell actual.Estamos
cd
ingresando a los directorios, buscando losfile*.tif
archivos y cambiándoles el nombre según sea necesario.manteniendo un contador incremental,
count
para cada archivo mientras se cambia el nombre
Lo anterior es una ejecución en seco y le mostrará el directorio donde se realizará el cambio de nombre y qué mv
comando se ejecutará. Si está satisfecho, haga:
shopt -s globstar
for d in **/*/; do ( cd "$d" && count=1 && shopt -s nullglob && \
for f in file*.tif; do mv -i "$f" "${f%.tif}"c${count}.tif; ((count++)); done ); done
Hay una advertencia: como Shell realiza una clasificación léxica, los archivos, por ejemplo, file10.tif
se cambiarán de nombre antes de file2.tif
. Si no desea eso, ordene un poco antes de cambiar el nombre o use la opción zsh
with numericglobsort
.
Respuesta3
Gracias a heemayl, todo se solucionó. Tuvimos que modificar un poco el bucle de incremento de ciclo indicado, ya que no funcionaba en nuestras manos. Cambiamos: if ((count=3)) a: if (("$count"==3)) El código final que ahora estamos usando exitosamente es:
shopt -s globstar
for d in **/*/; do
( cd "$d" && count=1 && shopt -s nullglob && for f in *.tif; do
echo mv -i "$f" "${f%.tif}"c${count}.tif
if (("$count"==3)); then
count=1
else
((count++))
fi
done )
done
Gracias de nuevo a heemayl por su ayuda y paciencia...