Navrhoval bych použít možnost filtrování rsync. Pro váš příklad stačí napsat:
rsync -vam -f'+ *[Nn][Aa][Mm][E]*' -f'+ */' -f'- *' a b
první pravidlo filtru říká rsync, jaké vzory má zahrnout. Druhé pravidlo je potřeba k tomu, abyste řekli rsync, aby zkontroloval všechny adresáře při průchodu. Aby se zabránilo zahrnutí prázdných adresářů, jsou explicitně vyloučeny pomocí -m
volba. Poslední pravidlo filtru říká rsync, aby zlikvidoval všechny zbývající vzory, které se dosud neshodovaly.
rsync nemluví regulární výraz. Můžete zařadit find a grep, i když to bude trochu tajemné. Chcete-li najít cílové soubory:
find a/ |
grep -i 'name'
Ale všechny mají předponu "a/" - což dává smysl, ale chceme skončit seznamem vzorů začlenění přijatelných pro rsync, a protože předpona "a/" pro rsync nefunguje, I' odstraníte jej řezem:
find . |
grep -i 'name' |
cut -d / -f 2-
Stále existuje problém - stále nám budou chybět soubory v podadresářích, protože rsync neprohledává adresáře v seznamu výjimek. Použiji awk k přidání podadresářů všech odpovídajících souborů do seznamu vzorů začlenění:
find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}'
Zbývá pouze odeslat seznam do rsync - můžeme použít argument --include-from=- k poskytnutí seznamu vzorů pro rsync na standardním vstupu. Takže celkem:
find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/
Všimněte si, že na zdrojový adresář 'a' se odkazuje dvěma různými cestami - "a/" a "./a/". To je jemné, ale důležité. Aby byly věci konzistentnější, udělám jednu poslední změnu a vždy budu odkazovat na zdrojový adresář jako "./a/". To však znamená, že příkaz cut se musí změnit, protože na přední straně výsledků z find bude navíc "./":
find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/
Pokud používáte ZSH, můžete pomocí příznaku (#i) vypnout rozlišování malých a velkých písmen. Příklad:
$ touch NAME
$ ls (#i)*name*
NAME
ZSH také podporuje výjimky, které jsou specifikovány stejně jako běžná cesta, ale mají počáteční ~
$ touch aa ab ac
$ ls *~*c
aa ab
Vyloučení můžete řetězit:
$ ls *~*c~*b
aa
Nakonec můžete určit, jaký druh souboru chcete vrátit (adresář, soubor atd.). To se provádí pomocí (/) pro adresář a (.) pro soubor.
$ touch file
$ mkdir dir
$ ls *(.)
file
Na základě toho všeho bych ten příkaz udělal jako:
rsync -avvz *(/) (#i)*name* ./a/ ./b/
(Nevidím potřebu vyloučení s těmito selektory)