Tengo una estructura de archivos como esta:
- 00000010
- 000000001.archivo1
- 000000001.archivo2
- 00000020
- 00000003.archivo1
- 00000003.archivo2
- 00000003.archivo3
- ...
Entonces, hay carpetas con nombres de 8 dígitos que contienen uno o más archivos con nombres que comienzan con números de 8 dígitos. Pero estos nombres de archivos están, digamos, no sincronizados. Ahora intento cambiarles el nombre de forma recursiva en bash para archivarlos:
- 00000010
- 000000010.archivo1
- 000000010.archivo2
- 00000020
- 00000020.archivo1
- 00000020.archivo2
- 00000020.archivo3
- ...
Mi guión se parece a:
#! /bin/bash
find * -maxdepth 1 -name "*" -type d | while read -r dir
do
rename 's/$dir\/[0-9]{8}/$dir/' *
done
Pero esto no funciona y da errores como
El símbolo global "$dir" requiere un nombre de paquete explícito en (eval 1) línea 1.
¿Cómo podría escribirlo para cambiar el nombre de los archivos según los nombres de sus carpetas?
¡Gracias por ayudar!
Respuesta1
A partir de otra respuesta aprendí que tengo que usar
rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/*
Por si alguien tiene el mismo problema...
Respuesta2
Realmente no me gusta la respuesta donde $dir
se interpola en el patrón. Podría generar resultados inesperados si el directorio contuviera, por ejemplo, un carácter que se interpreta como un token de expresión regular especial.
Preferiría hacer coincidir los archivos directamente en el patrón, eliminando la necesidad de recorrer los directorios y simplemente usar un globo normal.
rename 's#([^/]+)/[^/]+(\.file[0-9]+)$#$1/$1$2#' base_directory/*/*
donde el globo llega a los archivos individuales dentro de los directorios (incluso podría especificarse como base_directory/*/*.file*
, o similar, pero no debería importar aquí).
Tenga en cuenta que este es el comando completo, sin necesidad de find
construcción.
- Lo uso
#
como separador en lugar del "normal"/
para evitar tener que escapar de eso en los patrones. - Capturo el grupo (codicioso) de "no es un separador de directorio", seguido de un separador de directorio, seguido de un nombre de archivo y un final de línea. Esto hace que el primer grupo de captura sea el directorio principal de cada archivo.
- La primera parte del nombre del archivo se descarta, excepto la terminación, para mantener el sufijo ordinal.
Elegí usar un enfoque más general que asumir que los archivos tenían 8 caracteres, pero la diferencia real es que no necesito la find
construcción ni meter la $dir
variable en el entorno de expresiones regulares (posiblemente inseguro).