Sugeriría usar la opción de filtro de rsync. Para su ejemplo, simplemente escriba:
rsync -vam -f'+ *[Nn][Aa][Mm][E]*' -f'+ */' -f'- *' a b
la primera regla de filtro le dice a rsync qué patrones incluir. La segunda regla es necesaria para decirle a rsync que inspeccione todos los directorios en su recorrido. Para evitar que se incluyan directorios vacíos, -m
los excluye explícitamente opción. La última regla de filtro le dice a rsync que elimine todos los patrones restantes que todavía no coincidían hasta ahora.
rsync no habla expresiones regulares. Puede utilizar find y grep, aunque se vuelve un poco arcano. Para encontrar los archivos de destino:
find a/ |
grep -i 'name'
Pero todos tienen el prefijo "a/", lo cual tiene sentido, pero queremos terminar con una lista de patrones de inclusión aceptables para rsync, y como el prefijo "a/" no funciona para rsync, Lo eliminaré con un corte:
find . |
grep -i 'name' |
cut -d / -f 2-
Todavía hay un problema:aún perderemos archivos en subdirectorios, porque rsync no busca directorios en la lista de exclusión. Voy a usar awk para agregar los subdirectorios de cualquier archivo coincidente a la lista de patrones de inclusión:
find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}'
Todo lo que queda es enviar la lista a rsync; podemos usar el argumento --include-from=- para proporcionar una lista de patrones para rsync en la entrada estándar. Entonces, en total:
find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/
Tenga en cuenta que se hace referencia al directorio de origen 'a' a través de dos rutas diferentes:"a/" y "./a/". Esto es sutil pero importante. Para hacer las cosas más consistentes, haré un cambio final y siempre me referiré al directorio fuente como "./a/". Sin embargo, esto significa que el comando de corte tiene que cambiar, ya que habrá un "./" adicional al frente de los resultados de find:
find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/
Si usa ZSH, puede usar el indicador (#i) para desactivar la distinción entre mayúsculas y minúsculas. Ejemplo:
$ touch NAME
$ ls (#i)*name*
NAME
ZSH también admite exclusiones, que se especifican como la ruta normal pero tienen un ~
inicial$ touch aa ab ac
$ ls *~*c
aa ab
Puede encadenar exclusiones:
$ ls *~*c~*b
aa
Finalmente, puede especificar qué tipo de archivo desea devolver (directorio, archivo, etc.). Esto se hace con (/) para directorio y (.) para archivo.
$ touch file
$ mkdir dir
$ ls *(.)
file
Basado en todo esto, haría ese comando como:
rsync -avvz *(/) (#i)*name* ./a/ ./b/
(No veo la necesidad de una exclusión con estos selectores)