rsync certains fichiers, à l'exclusion du reste, en ignorant le répertoire .svn /, récursivement

19

J'utilise rsyncpour copier certains fichiers d'un partage à un autre.

Récursivement, je dois:

  • Supprimer les fichiers à destination qui ont été supprimés de l'origine
  • Synchronisation .phpet .jsfichiers uniquement
  • Exclure tous les autres types de fichiers
  • Ne supprimez pas les .svn/répertoires à destination

Si j'utilise ceci:

rsync -zavC --delete --include='*.php' --include='*.js' --exclude="*" \
    /origin /destination

N'est alors rsyncpas récursif car exclude="*"exclut tous les fichiers mais aussi les dossiers.

Si j'ajoute, --include="*/"le .svn/répertoire est supprimé (il est également inclus).

Comment puis-je résoudre ce dilemme de dynamitage de l'esprit?

uname -a:

Linux tux 3.9.2-1-ARCH # 1 SMP PREEMPT sam. 11 mai 20:31:08 CEST 2013 x86_64 GNU / Linux

rsync version:

rsync 3.0.9-6
canolucas
la source

Réponses:

13

1ère tentative (n'a pas fonctionné)

Vous devez inclure les répertoires en plus des fichiers:

rsync -zavC --delete --include '*/' --include='*.php' --include='*.js' \
     --exclude="*" /media/datacod/Test/ /home/lucas/Desktop/rsync/

2e tentative

rsync -avzC --filter='-rs_*/.svn*' --include="*/" --include='*.js' \
     --include='*.php' --exclude="*" --delete dir1/ dir2/

données de test

J'ai écrit ce script pour créer des exemples de données pour tester cela. Voici ce script, setup_svn_sample.bash:

#!/bin/bash

# setup .svn dirs
mkdir -p dir{1,2}/dir{1,2,3,4}/.svn

# fake data under .svn
mkdir -p dir1/dir{1,2,3,4}/.svn/origdir
mkdir -p dir2/dir{1,2,3,4}/.svn/keepdir

# files to not sync
touch dir1/dir{1,2,3,4}/file{1,2}

# files to sync
touch dir1/dir{1,2,3,4}/file1.js
touch dir1/dir{1,2,3,4}/file1.php

Son exécution produit les répertoires suivants:

répertoire source

$ tree -a dir1
dir1
|-- dir1
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
|-- dir2
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
|-- dir3
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
`-- dir4
    |-- file1
    |-- file1.js
    |-- file1.php
    |-- file2
    `-- .svn
        `-- origdir

répertoire de destination

$ tree -a dir2
dir2
|-- dir1
|   `-- .svn
|       `-- keepdir
|-- dir2
|   `-- .svn
|       `-- keepdir
|-- dir3
|   `-- .svn
|       `-- keepdir
`-- dir4
    `-- .svn
        `-- keepdir

Exécution de la rsynccommande ci-dessus :

rsync -avzC --filter='-rs_*/.svn*' --include="*/" --include='*.js' \
     --include='*.php' --exclude="*" --delete dir1/ dir2/
sending incremental file list
dir1/file1.js
dir1/file1.php
dir2/file1.js
dir2/file1.php
dir3/file1.js
dir3/file1.php
dir4/file1.js
dir4/file1.php

sent 480 bytes  received 168 bytes  1296.00 bytes/sec
total size is 0  speedup is 0.00

Résultat dir2 suivant:

$ tree -a dir2
dir2
|-- dir1
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
|-- dir2
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
|-- dir3
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
`-- dir4
    |-- file1.js
    |-- file1.php
    `-- .svn
        `-- keepdir

Pourquoi ça marche?

L'élément clé de ce script est d'utiliser la capacité des filtres de rsync. Les filtres vous permettent de supprimer des fichiers de l'ensemble correspondant à différents points de la commande. Donc, dans notre cas, nous filtrons tous les fichiers qui correspondent au modèle */.svn*. Les modificateurs -rs_indiquent au filtre que nous voulons filtrer à la fois du côté source et du côté cible.

extrait de la section FILTER NOTES de la page de manuel de rsync

  • Un s est utilisé pour indiquer que la règle s'applique au côté émetteur. Lorsqu'une règle affecte le côté d'envoi, elle empêche le transfert de fichiers. Par défaut, une règle affecte les deux côtés, sauf indication --delete-excludedcontraire, auquel cas les règles par défaut deviennent uniquement côté expéditeur. Voir aussi les règles hide (H) et show (S), qui sont un autre moyen de spécifier les inclusions / exclusions côté envoi.

  • Un r est utilisé pour indiquer que la règle s'applique au côté récepteur. Lorsqu'une règle affecte le côté récepteur, elle empêche la suppression de fichiers. Voir le modificateur s pour plus d'informations. Voir également les règles de protection (P) et de risque (R), qui sont un autre moyen de spécifier les inclusions / exclusions côté récepteur.

Voir man rsync pour plus de détails.

Conseils pour comprendre cela (conseil d'utilisation --dry-run)

En décrivant comment procéder, j'ai pensé mentionner le --dry-runpassage à rsync. Il est extrêmement utile de voir ce qui se passera sans que cela se produise rsyncréellement.

Par exemple

L'utilisation de la commande suivante fera un test et nous montrera la logique de décision derrière rsync:

rsync --dry-run -avvzC --filter='-rs_*/.svn*' --include="*/" \
     --include='*.js' --include='*.php' --exclude="*" --delete dir1/ dir2/
sending incremental file list
[sender] showing directory dir3 because of pattern */
[sender] showing directory dir2 because of pattern */
[sender] showing directory dir4 because of pattern */
[sender] showing directory dir1 because of pattern */
[sender] hiding file dir1/file1 because of pattern *
[sender] showing file dir1/file1.js because of pattern *.js
[sender] hiding file dir1/file2 because of pattern *
[sender] showing file dir1/file1.php because of pattern *.php
[sender] hiding directory dir1/.svn because of pattern */.svn*
[sender] hiding file dir2/file1 because of pattern *
[sender] showing file dir2/file1.js because of pattern *.js
[sender] hiding file dir2/file2 because of pattern *
[sender] showing file dir2/file1.php because of pattern *.php
[sender] hiding directory dir2/.svn because of pattern */.svn*
[sender] hiding file dir3/file1 because of pattern *
[sender] showing file dir3/file1.js because of pattern *.js
[sender] hiding file dir3/file2 because of pattern *
[sender] showing file dir3/file1.php because of pattern *.php
[sender] hiding directory dir3/.svn because of pattern */.svn*
[sender] hiding file dir4/file1 because of pattern *
[sender] showing file dir4/file1.js because of pattern *.js
[sender] hiding file dir4/file2 because of pattern *
[sender] showing file dir4/file1.php because of pattern *.php
[sender] hiding directory dir4/.svn because of pattern */.svn*
delta-transmission disabled for local transfer or --whole-file
[generator] risking directory dir3 because of pattern */
[generator] risking directory dir2 because of pattern */
[generator] risking directory dir4 because of pattern */
[generator] risking directory dir1 because of pattern */
[generator] protecting directory dir1/.svn because of pattern */.svn*
dir1/file1.js
dir1/file1.php
[generator] protecting directory dir2/.svn because of pattern */.svn*
dir2/file1.js
dir2/file1.php
[generator] protecting directory dir3/.svn because of pattern */.svn*
dir3/file1.js
dir3/file1.php
[generator] protecting directory dir4/.svn because of pattern */.svn*
dir4/file1.js
dir4/file1.php
total: matches=0  hash_hits=0  false_alarms=0 data=0

sent 231 bytes  received 55 bytes  572.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)

Dans la sortie ci-dessus, vous pouvez voir que les ./svnrépertoires sont protégés par notre règle de filtrage. Informations précieuses pour le débogage du rsync.

Les références

slm
la source
J'ai déjà essayé cela, comme je l'ai dit plus haut. Si je fais cela, le répertoire .SVN est également inclus (très probablement supprimé, car il n'existe pas dans l'origine ou modifié). Il est essentiel de laisser le répertoire .SVN intact. Merci pour l'essayer quand même! :)
canolucas
-C est censé ignorer ".SVN /", mais l' include="*/"inclut
canolucas
Tu as raison. Cela devrait être .svn, en éditant la réponse. Quoi qu'il en soit, après avoir renommé le problème, il reste. -Cet include="*/"ne semblent pas être des amis très proches :(
canolucas
10

Ok, après plusieurs essais, j'ai trié ceci:

rsync -vaiz --delete --exclude=.svn/ --include='*.php' --include='*.js' \
    --include='*/' --exclude='*' --prune-empty-dirs \
    --filter "protect .svn/" /origin /destination

Je vous remercie

canolucas
la source
Très bonne réponse. Mon filtre protège les .svn/répertoires --prune-empty-dirss'ils sont vides. Une autre approche, celle-ci dupliquant des rsync -vaiz --delete --exclude=.svn/ --include='*.php' --include='*.js' --include='*/' --exclude='*' /origin /destination
dires
La clé de mon approche est --exclude=.svn/avant le --include's
canolucas
Bonne réponse aussi. J'aurais suggéré un exclude = '. Svn /' mais je pensais que vous vouliez utiliser le -C. Je suis content que vous l'aillez compris!
slm
0

Bien que cela n'utilise pas rsync, une autre option consiste à utiliser find et cpio. Par exemple, j'ai un répertoire appelé Photos et celui de l'année et du mois.

Photos
├── 2002
   ├── 2002-03
      ├── 2002-03-30
      ├── 2002-03-31
      └── 2002-03-31-02
   ├── 2002-04
      ├── 2002-04-01
      ├── 2002-04-01-03
      ├── 2002-04-07
      ├── 2002-04-21
      ├── 2002-04-22
      ├── 2002-04-22-02
      └── 2002-04-27
   ├── 2002-05
      ├── 2002-05-02
      ├── 2002-05-03

Mais ici, j'ai jpg, dng, xml et d'autres choses et je veux juste les jpg donc je ferais ça

"cd" dans le répertoire au dessus du répertoire Photos puis:

find Photos -type f -name "*jpg" -print | cpio -pdmvu /fast

Et c'est parti

/fast/Photos/2002/2002-04/2002-04-22/bath problem.jpg
/fast/Photos/2002/2002-04/2002-04-22-02/full bath.jpg
/fast/Photos/2002/2002-07/2002-07-10/Broken Top.jpg
/fast/Photos/2002/2002-12/2002-12-28/101-0125_IM~~G.jpg
/fast/Photos/2002/2002-12/2002-12-28/small-101-0125_IM~~G.jpg
/fast/Photos/2003/2003-01/2003-01-19/k1.jpg
/fast/Photos/2003/2003-01/2003-01-19/k2.jpg
/fast/Photos/2003/2003-02/2003-02-23/quinn.jpg
/fast/Photos/2003/2003-05/2003-05-04/all.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0015_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0006_2_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0006_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0007_2_r1.jpg

Vous pouvez utiliser cette méthode pour beaucoup de choses, il y a des années, c'est ainsi que nous copions le système de fichiers / lors du déplacement vers des disques plus gros, car cela copierait des fichiers de périphérique.

lxtwin
la source
Cela ne répond pas à la question.
RalfFriedl
Il le fait s'il utilise: find / origin -type f (-name " .php" -o -name " .js") -print | cpio -pdmvu / destination Seuls les fichiers * .php et * .js seront dans le répertoire cible.
lxtwin