Je suggérerais d'utiliser l'option de filtrage de rsync. Pour votre exemple, tapez simplement :
rsync -vam -f'+ *[Nn][Aa][Mm][E]*' -f'+ */' -f'- *' a b
la première règle de filtrage indique à rsync les modèles à inclure. La deuxième règle est nécessaire pour indiquer à rsync d'inspecter tous les répertoires lors de sa traversée. Pour empêcher l'inclusion des répertoires vides, ils sont explicitement exclus par -m
option. La dernière règle de filtrage indique à rsync de supprimer tous les modèles restants qui ne correspondent toujours pas jusqu'à présent.
rsync ne parle pas regex. Vous pouvez enrôler find et grep, bien que cela devienne un peu mystérieux. Pour trouver les fichiers cibles :
find a/ |
grep -i 'name'
Mais ils sont tous préfixés par "a/" - ce qui est logique, mais ce que nous voulons obtenir est une liste de modèles d'inclusion acceptables pour rsync, et comme le préfixe "a/" ne fonctionne pas pour rsync I' Je vais le supprimer en coupant :
find . |
grep -i 'name' |
cut -d / -f 2-
Il y a toujours un problème - nous manquerons toujours des fichiers dans les sous-répertoires, car rsync ne recherche pas les répertoires dans la liste d'exclusion. Je vais utiliser awk pour ajouter les sous-répertoires de tous les fichiers correspondants à la liste des modèles d'inclusion :
find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}'
Il ne reste plus qu'à envoyer la liste à rsync - nous pouvons utiliser l'argument --include-from=- pour fournir une liste de motifs à rsync sur l'entrée standard. Donc, tout à fait :
find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/
Notez que le répertoire source 'a' est référencé via deux chemins différents - "a/" et "./a/". C'est subtil mais important. Pour rendre les choses plus cohérentes, je vais apporter une dernière modification et toujours faire référence au répertoire source par "./a/". Cependant, cela signifie que la commande de coupe doit changer car il y aura un "./" supplémentaire devant les résultats 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 vous utilisez ZSH, vous pouvez utiliser le drapeau (#i) pour désactiver la sensibilité à la casse. Exemple :
$ touch NAME
$ ls (#i)*name*
NAME
ZSH prend également en charge les exclusions, qui sont spécifiées comme le chemin normal, mais elles ont un ~
initial$ touch aa ab ac
$ ls *~*c
aa ab
Vous pouvez enchaîner les exclusions :
$ ls *~*c~*b
aa
Enfin, vous pouvez spécifier le type de fichier que vous souhaitez renvoyer (répertoire, fichier, etc.). Cela se fait avec (/) pour répertoire et (.) pour fichier.
$ touch file
$ mkdir dir
$ ls *(.)
file
Sur la base de tout cela, je ferais cette commande comme :
rsync -avvz *(/) (#i)*name* ./a/ ./b/
(Je ne vois pas la nécessité d'une exclusion avec ces sélecteurs)