rsync copie uniquement certains types de fichiers à l'aide de l'option d'inclusion

110

J'utilise le script bash suivant pour copier uniquement les fichiers de certaines extensions (dans ce cas * .sh), mais il copie toujours tous les fichiers. Qu'est-ce qui ne va pas?

à partir de = 1 $
à = 2 $

rsync -zarv --include = "*. sh" $ de $ à
user881480
la source
4
Bien que n'étant pas strictement parlant, je suggérerais de citer $ de / $ à. Ne pas le faire peut vous donner des résultats inattendus si les arguments positionnels 1/2 incluent des espaces.
Kjetil Joergensen
avez-vous compris pourquoi votre commande ne fonctionnerait pas simplement?
Charlie Parker
@CharlieParker: Devez-vous utiliser rsync, cela peut très bien être réalisé avec les internes du shell?
Inian
Ce qui manque également à cette question et à ses réponses, c'est de savoir comment créer la commande si j'ai des répertoires récursifs auxquels je souhaite envoyer un seul type de fichier. Il semble qu'il ne le fait que pour le répertoire cible ...
Charlie Parker

Réponses:

200

Je pense qu'il --includeest utilisé pour inclure un sous-ensemble de fichiers qui sont autrement exclus par --exclude, plutôt que d'inclure uniquement ces fichiers. En d'autres termes: vous devez penser à inclure le sens, ne pas exclure .

Essayez plutôt:

rsync -zarv  --include "*/" --exclude="*" --include="*.sh" "$from" "$to"

Pour rsync version 3.0.6 ou supérieure, l'ordre doit être modifié comme suit (voir commentaires):

rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"

L'ajout de l' -mindicateur évitera de créer des structures de répertoires vides dans la destination. Testé en version 3.1.2.

Donc, si nous ne voulons que des fichiers * .sh, nous devons exclure tous les fichiers --exclude="*", inclure tous les répertoires --include="*/"et inclure tous les fichiers * .sh --include="*.sh".

Vous pouvez trouver quelques bons exemples dans la section Inclure / Exclure les règles de modèle de la page de manuel

chepner
la source
10
Bien que cela vous donne tous les sous-répertoires, s'il y a des fichiers .sh dans les sous-répertoires que vous voulez rsync, il y a de fortes chances que vous souhaitiez utiliser --include = "* /" aussi.
Kjetil Joergensen
50
J'ai essayé cela sur rsync version 3.0.7, que j'ai obtenue il y a longtemps de macports, et cela ne fonctionnait pas avec cet ordre d'inclusions / exclus. C'est ce que j'ai fini avec cela a fonctionné pour moi (adapté pour OP): rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to".
Bijou Trouvaille
3
J'ai essayé avec rsync 3.0.9 et cela n'a pas fonctionné. Bijou est juste, la commande ne convient pas (première --include=\*.shalors --exclude=\*)
TrueY
3
Notez que vous pouvez toujours cliquer sur Modifier et suggérer une modification à la réponse :)
Achal Dave
2
Cela ne fonctionne pas avec votre commande d'inclus / exclut, mais cela fonctionne avec la commande suggérée par Bijou Trouvaille
John Smith Facultatif
57

La réponse de @chepner copiera tous les sous-répertoires indépendamment du fait qu'il contienne le fichier ou non. Si vous devez exclure les sous-répertoires qui ne contiennent pas le fichier tout en conservant la structure de répertoires, utilisez

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
ErrantEsprit
la source
1
C'était une exigence pour moi: "Si vous avez besoin d'exclure les sous-répertoires qui ne contiennent pas le fichier tout en conservant la structure des répertoires" +1
Juuso Ohtonen
1
Je ne comprends pas comment avez-vous su quel était l'ordre des - inclus?
Charlie Parker
1
Comment fabrique-t-on la commande si j'ai des répertoires récursifs auxquels je ne souhaite envoyer qu'un seul type de fichier. Il semble qu'il ne le fasse que pour le répertoire cible.
Charlie Parker
15

Un autre ajout: si vous avez besoin de synchroniser des fichiers par ses extensions dans un seul (sans récursivité), vous devez utiliser une construction comme celle-ci:

rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/

Faites attention au point dans le premier --include . --no-rne fonctionne pas dans cette construction.

ÉDITER:

Merci à gbyte.co pour le précieux commentaire!

Serge Roussak
la source
1
Comment saviez-vous quel devait être l'ordre des drapeaux et ce qu'ils devaient inclure?
Charlie Parker
1
@CharlieParker, parce que le rsync utilise includeet les excludeoptions dans l'ordre où ils ont été précisées dans. En plus de cela, il arrête au premier apparié. Donc, si nous spécifions le --exclude '*'à la première place dans cet exemple, rsync ne fera rien. Voir l'homme pour plus d'explications.
Serge Roussak
pouvez-vous m'expliquer ce que fait chaque drapeau? Le premier drapeau -- include './' dit tout inclure dans le chemin du répertoire source? Ensuite, le suivant `--include '.ext'` inclut le fichier spécifique dans le chemin source nommé .ext, puis l'exclusion dit de ne rien envoyer d'autre --exclude '*'? Est-ce exact?
Charlie Parker
1
Comment fabrique-t-on la commande si j'ai des répertoires récursifs auxquels je ne souhaite envoyer qu'un seul type de fichier. Il semble qu'il ne le fasse que pour le répertoire cible.
Charlie Parker
1
Merci pour cela! Besoin --include '*.ext'et pas--include '.ext'
gbyte le
13

Voici la partie importante de la page de manuel:

Lorsque la liste des fichiers / répertoires à transférer est construite, rsync vérifie chaque nom à transférer par rapport à la liste des modèles d'inclusion / exclusion, et le premier modèle correspondant est appliqué: s'il s'agit d'un modèle d'exclusion, alors ce fichier est ignoré; s'il s'agit d'un modèle d'inclusion, ce nom de fichier n'est pas ignoré; si aucun modèle correspondant n'est trouvé, le nom de fichier n'est pas ignoré.

Résumer:

  • Ne correspondant à aucun modèle signifie qu'un fichier sera copié!
  • L'algorithme se ferme une fois qu'un motif correspond

De plus, quelque chose se terminant par une barre oblique correspond aux répertoires (comme le find -type dferait).

Séparons cette réponse d'en haut.

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. Ne sautez aucun répertoire
  2. Ne sautez aucun .shfichier
  3. Passer tout
  4. (Implicitement, ne sautez rien, mais la règle ci-dessus empêche la règle par défaut de se produire.)

Enfin, le --prune-empty-directoriesgarde la première règle de créer des répertoires vides partout.

Jim Hunziker
la source
Merci beaucoup d'avoir expliqué ce qui se passe. Maintenant, il y a de bien meilleures chances que je n'oublie pas la commande.
MohamedEzz
3
« » L'algorithme quittes une fois que tous les matches de motif » - ce qui est essentiel, et aucune des réponses mieux notés , expliquer aussi clairement et à l'avance que vous avez fait ici Bien sûr , cela. Est dans la page de manuel somehwere, et si je J'avais lu le tout attentivement, j'avais vu ça. Encore, merci.
TheDudeAbides
0

Si quelqu'un cherche cela ... je voulais rsync uniquement des fichiers et dossiers spécifiques et j'ai réussi à le faire avec cette commande: rsync --include-from=rsync-files

Avec les fichiers rsync:

my-dir/
my-file.txt

- /*
Pascal Polleunus
la source
0

J'ai écrit cette fonction pratique et mis dans mes scripts bash ou ~/.bash_aliases. Testé la synchronisation localement sur Linux avec bash et awkinstallé. Ça marche

selrsync(){
# selective rsync to sync only certain filetypes;
# based on: https://stackoverflow.com/a/11111793/588867
# Example: selrsync 'tsv,csv' ./source ./target --dry-run
types="$1"; shift; #accepts comma separated list of types. Must be the first argument.
includes=$(echo $types| awk  -F',' \
    'BEGIN{OFS=" ";}
    {
    for (i = 1; i <= NF; i++ ) { if (length($i) > 0) $i="--include=*."$i; } print
    }')
restargs="$@"

echo Command: rsync -avz --prune-empty-dirs --include="*/" $includes --exclude="*" "$restargs"
eval rsync -avz --prune-empty-dirs --include="*/" "$includes" --exclude="*" $restargs
}

Avantages:

bref pratique et extensible quand on veut ajouter plus d'arguments (ie --dry-run).

Exemple:

selrsync 'tsv,csv' ./source ./target --dry-run
biocyberman
la source