15 votes

rsync utilisant une expression rationnelle pour inclure seulement certains fichiers

J'essaie d'exécuter rsync pour copier des fichiers de manière récursive le long d'un chemin en fonction de leur modèle de nom de fichier, en respectant la casse. insensible . C'est ce que j'ai fait pour exécuter rsync :

$ rsync -avvz --include ='*/' --include='.*[Nn][Aa][Mm][E].*' --exclude='*' ./a/ ./b/

Rien n'est copié, la sortie de débogage montre :

[sender] hiding file 1Name.txt because of pattern *
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] hiding directory test1 because of pattern *
[sender] hiding file NaMe.txt because of pattern *

J'ai essayé d'utiliser : --include='*[Nn][Aa][Mm][E]*' et d'autres combinaisons mais ça ne marche toujours pas.

Des idées sur la façon d'utiliser l'expression rationnelle pour inclure certains fichiers ?

10voto

sparkie Points 2200

Je vous suggère d'utiliser l'option filtre 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 motifs à inclure. La deuxième règle est nécessaire pour indiquer à rsync d'inspecter tous les répertoires lors de sa traversée. Pour éviter l'inclusion des répertoires vides, ils sont exclus explicitement par la règle suivante -m option. La dernière règle de filtrage indique à rsync de se débarrasser de tous les motifs restants qui ne correspondent toujours pas jusqu'à présent.

6voto

sqweek Points 396

Rsync ne parle pas le regex. Vous pouvez faire appel à find et grep, mais cela devient un peu obscur. 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, je le supprimerai avec cut :

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, parce que 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 motifs d'inclusion :

find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}'

Tout ce qui reste à faire est d'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 compte 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é par deux chemins différents - "a/" et "./a/". C'est subtil mais important. Pour rendre les choses plus cohérentes, je vais faire un dernier changement, et toujours faire référence au répertoire source comme "./a/". Cependant, cela signifie que la commande cut doit être modifiée car il y aura un "./" supplémentaire au début des 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/

2voto

Matthew Franglen Points 331

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 de la même manière que le chemin d'accès normal, mais avec 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 obtenir (répertoire, fichier, etc.). Ceci est fait avec (/) pour le répertoire et (.) pour le fichier.

$ touch file
$ mkdir dir
$ ls *(.)
file

Compte tenu de tout cela, je ferais cette commande comme.. :

rsync -avvz *(/) (#i)*name* ./a/ ./b/

(Je ne vois pas l'utilité d'une exclusion avec ces sélecteurs).

1voto

Ryan Williams Points 11

La réponse de @sqweek ci-dessus est géniale, bien que je soupçonne qu'il ait un bug dans son système de gestion de l'information. awk script pour générer des répertoires parents, car cela me donne par exemple :

$ echo a/b/c/d | awk -F/ '{print; while(/\//) {sub("/[^/]*", ""); print}}'
a/b/c/d
a/c/d
a/d
a

J'ai pu le réparer en utilisant gensub à la place :

$ echo a/b/c/d | awk -F/ '{print; while(/\//) { $0=gensub("(.*)/[^/]*", "\\1", "g"); print}}'
a/b/c/d
a/b/c
a/b
a

Donc, sa solution complète, avec le awk un peu changé, serait :

find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) { $0=gensub("(.*)/[^/]*", "\\1", "g"); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/

0voto

user1957413 Points 173

J'ai essayé avec un script C# puisque c'est le langage avec lequel j'ai le plus d'expérience. Je suis capable de créer la liste des fichiers que je veux inclure, mais quelqu'un rsync est toujours me dire take a hike. Il crée les dossiers, mais il ignore les fichiers. Voici ce que j'ai obtenu

D'abord le contenu du répertoire :

~/mono$ ls -l
total 24
drwxr-xr-x 5 me me 4096 Jan 15 00:36 a
drwxr-xr-x 2 me me 4096 Jan 15 00:36 b
drwxr-xr-x 3 me me 4096 Jan 14 00:31 bin
-rw-r--r-- 1 me me 3566 Jan 15 00:31 test.cs
-rwxr-xr-x 1 me me 4096 Jan 15 00:31 test.exe
-rwxr--r-- 1 me me  114 Jan 14 22:40 test.sh

Puis la sortie du script de C# :

~/mono$ mono test.exe

/a/myfile/myfileseries.pdf
/a/myfile2/testfile.pdf

Et la sortie de débogage :

~/mono$ mono test.exe | rsync -avvvz --include='*/' --include-from=- --exclude='*' ./a/ ./b/
[client] add_rule(+ */)
[client] parse_filter_file(-,20,3)
[client] add_rule(+ /a/myfile/myfileseries.pdf)
[client] add_rule(+ /a/myfile2/testfile.pdf)
[client] add_rule(- *)
sending incremental file list
[sender] make_file(.,*,0)
[sender] hiding file 1Name.txt because of pattern *
[sender] showing directory myfile2 because of pattern */
[sender] make_file(myfile2,*,2)
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] showing directory test1 because of pattern */
[sender] make_file(test1,*,2)
[sender] hiding file NaMe.txt because of pattern *
[sender] showing directory myfile because of pattern */
[sender] make_file(myfile,*,2)
send_file_list done
send_files starting
[sender] hiding file myfile/myfileseries.pdf because of pattern *
[sender] hiding file myfile2/testfile.pdf because of pattern *
[sender] hiding file test1/test.txt because of pattern *

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X