158 votes

Rsync copie uniquement certains types de fichiers en utilisant l'option inclure

J'utilise le script bash suivant pour copier uniquement les fichiers ayant une certaine extension(dans ce cas *.sh), cependant il copie toujours l'ensemble des fichiers. Qu'est-ce qui ne va pas?

from=$1
to=$2

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

341voto

chepner Points 54078

Je pense que -- inclure est utilisé pour inclure un sous-ensemble de fichiers qui sont sinon exclus par -- exclure, plutôt que d'inclure seulement ces fichiers. En d'autres termes: vous devez penser à inclure signifiant 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 les commentaires):

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

Ajouter le drapeau -m évitera la création de structures de répertoire vides dans la destination. Testé dans la version 3.1.2.

Donc si nous voulons seulement les fichiers *.sh nous devons exclure tous les fichiers --exclure="*", inclure tous les répertoires --inclure="*/" et inclure tous les fichiers *.sh --inclure="*.sh".

Vous pouvez trouver de bons exemples dans la section Règles de modèles d'inclusion/exclusion de la page de l'homme

77voto

WanderingMind Points 847

La réponse de @chepner copiera tous les sous-répertoires qu'ils contiennent des fichiers ou non. Si vous avez besoin d'exclure les sous-répertoires qui ne contiennent pas le fichier et de conserver la structure du répertoire, utilisez

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

47voto

Jim Hunziker Points 1844

Voici la partie importante de la page de manuel :

Alors que la liste des fichiers/répertoires à transférer est construite, rsync vérifie chaque nom à transférer par rapport à la liste des modèles inclus/exclus tour à tour, 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, alors ce nom de fichier ne sera pas ignoré ; si aucun modèle correspondant n'est trouvé, alors le nom de fichier n'est pas ignoré.

Pour résumer :

  • Un fichier qui ne correspond à aucun modèle sera copié !
  • L'algorithme s'arrête dès qu'un modèle correspond

Aussi, quelque chose se terminant par un slash correspond aux répertoires (comme le ferait find -type d).

Décomposons maintenant cette réponse ci-dessus.

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. Ne pas ignorer les répertoires
  2. Ne pas ignorer les fichiers .sh
  3. Ignorer tout
  4. (Implicitement, ne pas ignorer quoi que ce soit, mais la règle précédente empêche la règle par défaut de se produire.)

Enfin, l'option --prune-empty-directories empêche la première règle de créer des répertoires vides partout.

20voto

Serge Roussak Points 111

Une autre addition : si vous avez besoin de synchroniser des fichiers par extensions dans un seul répertoire (sans récursivité), vous devriez 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-r ne fonctionne pas dans cette construction.

ÉDIT :

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

ÉDIT :

Les indicateurs -uzv ne sont pas directement liés à cette question, mais je les ai inclus car je les utilise habituellement.

3voto

biocyberman Points 311

Écrivez cette fonction pratique et placez-la dans mes scripts bash ou ~/.bash_aliases. Testé la synchronisation localement sur Linux avec bash et awk installé. Ça marche

selrsync(){
# rsync sélectif pour synchroniser uniquement certains types de fichiers;
# basé sur: https://stackoverflow.com/a/11111793/588867
# Exemple: selrsync 'tsv,csv' ./source ./target --dry-run
types="$1"; shift; #accepte une liste séparée par des virgules de types. Doit être le premier argument.
includes=$(echo $types| awk  -F',' \
    'BEGIN{OFS=" ";}
    {
    for (i = 1; i <= NF; i++ ) { if (length($i) > 0) $i="--include=*."$i; } print
    }')
restargs="$@"

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

Avantages:

court, pratique et extensible lorsque l'on veut ajouter plus d'arguments (par exemple, --dry-run).

Exemple:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X