Comment rsynchroniser uniquement une liste spécifique de fichiers?

93

J'ai environ 50 fichiers dans divers sous-répertoires que je voudrais pousser vers un serveur distant. J'ai pensé que rsync serait capable de le faire pour moi en utilisant l'option --include-from. Sans l'option --exclude = "*", tous les fichiers du répertoire sont synchronisés, avec l'option, aucun fichier ne l'est.

rsync -avP -e ssh --include-from=deploy/rsync_include.txt --exclude=* ./ [email protected]:/var/www/ --dry-run

Je l'exécute aussi sec au départ et 0.0.0.0 est évidemment remplacé par l'adresse IP du serveur distant. Le contenu de rsync_include.txt est une nouvelle liste de chemins relatifs séparés par une ligne vers les fichiers que je souhaite télécharger.

Y a-t-il une meilleure façon de faire cela qui m'échappe un lundi matin?

Dan Steele
la source

Réponses:

3

Edit: La réponse de Josip Rodin ci-dessous est meilleure. Veuillez utiliser celui-là!

Vous pourriez avoir plus de facilité, si vous recherchez une liste spécifique de fichiers, en les plaçant directement sur la ligne de commande à la place:

# rsync -avP -e ssh `cat deploy/rsync_include.txt` [email protected]:/var/www/

Ceci suppose, cependant, que votre liste n'est pas si longue que la longueur de la ligne de commande sera un problème et que le rsync_include.txtfichier ne contient que des chemins réels (c'est-à-dire pas de commentaires, et pas d'expressions rationnelles).

Wes Hardaker
la source
9
Malheureusement, cela ne fonctionne pas avec une grande liste ou avec des fichiers avec des espaces dans le nom.
Wes Modes
3
[Liste d'arguments trop longue]
Dankó Dávid
Par défaut, xargs ajoute des arguments de stdin à la fin de la ligne de commande. Cela ne fonctionne pas car rsync a besoin du dernier argument pour être la destination. Certaines versions de xargs peuvent éventuellement insérer des arguments au milieu de la ligne de commande à la place. Cela devrait fonctionner tant que cela ne vous dérange pas qu'il puisse exécuter rsync plus d'une fois lorsque la liste des fichiers est longue. Dans tous les cas, rsync --files-fromc'est probablement une solution plus simple et plus fiable :)
Lassi
Wes Hardaker: Est-ce que votre édition et votre référence à "la réponse de Josip Rodin" se réfèrent réellement à la réponse @atp que Rodin a éditée?
Seamus
228

Il y a un drapeau --files-fromqui fait exactement ce que vous voulez. De man rsync:

--files-from=FILE

L'utilisation de cette option vous permet de spécifier la liste exacte des fichiers à transférer (comme lu à partir du FICHIER spécifié ou - pour l'entrée standard). Il modifie également le comportement par défaut de rsync pour faciliter le transfert uniquement des fichiers et répertoires spécifiés:

  • L'option --relative (-R) est implicite, ce qui préserve les informations de chemin spécifiées pour chaque élément du fichier (utilisez --no-relative ou --no-R si vous souhaitez désactiver cette option).

  • L'option --dirs (-d) est implicite, qui créera les répertoires spécifiés dans la liste sur la destination plutôt que de les sauter bruyamment (utilisez --no-dirs ou --no-d si vous voulez désactiver cela).

  • Le comportement de l'option --archive (-a) n'implique pas --recursive (-r), alors spécifiez-le explicitement, si vous le souhaitez.

  • Ces effets secondaires modifient l'état par défaut de rsync, donc la position de l'option --files-from sur la ligne de commande n'a aucune incidence sur la façon dont les autres options sont analysées (par exemple, -a fonctionne de la même manière avant ou après --files- from, comme le fait --no-R et toutes les autres options).

Les noms de fichiers lus à partir du FICHIER sont tous relatifs au répertoire source - toutes les barres obliques sont supprimées et aucune référence ".." n'est autorisée à aller plus haut que le répertoire source. Par exemple, prenez cette commande:

rsync -a --files-from=/tmp/foo /usr remote:/backup

Si / tmp / foo contient la chaîne "bin" (ou même "/ bin"), le répertoire / usr / bin sera créé en tant que / backup / bin sur l'hôte distant. S'il contient "bin /" (notez la barre oblique de fin), le contenu immédiat du répertoire sera également envoyé (sans avoir besoin d'être explicitement mentionné dans le fichier - cela a commencé dans la version 2.6.4). Dans les deux cas, si l'option -r était activée, toute la hiérarchie de ce répertoire serait également transférée (gardez à l'esprit que -r doit être spécifié explicitement avec --files-from, car il n'est pas impliqué par -a). Notez également que l'effet de l'option (activée par défaut) --relative est de ne dupliquer que les informations de chemin lues à partir du fichier - cela ne force pas la duplication du chemin source-spec (/ usr dans ce cas) .

De plus, le fichier --files-from peut être lu depuis l'hôte distant au lieu de l'hôte local si vous spécifiez un "hôte:" devant le fichier (l'hôte doit correspondre à une extrémité du transfert). Comme raccourci, vous pouvez spécifier juste un préfixe de ":" pour signifier "utiliser l'extrémité distante du transfert". Par exemple:

rsync -a --files-from=:/path/file-list src:/ /tmp/copy

Cela copierait tous les fichiers spécifiés dans le fichier / path / file-list qui se trouvait sur l'hôte distant "src".

Si les options --iconv et --protect-args sont spécifiées et que les noms de fichiers --files-from sont envoyés d'un hôte à un autre, les noms de fichiers seront traduits du jeu de caractères de l'hôte émetteur vers le jeu de caractères de l'hôte récepteur.

REMARQUE: le tri de la liste des fichiers dans l'entrée --files-from permet à rsync d'être plus efficace, car cela évitera de visiter à nouveau les éléments de chemin partagés entre les entrées adjacentes. Si l'entrée n'est pas triée, certains éléments de chemin (répertoires implicites) peuvent finir par être analysés plusieurs fois et rsync finira par les dédupliquer après avoir été transformés en éléments de liste de fichiers.

atp
la source
22
Notez que vous devez toujours spécifier le répertoire où se trouvent les fichiers listés, par exemple: rsync -av --files-from=file-list . target/pour copier des fichiers depuis le répertoire courant.
Nicolas Mattia
7
Oui, et demander de nouveau: The filenames that are read from the FILE are all relative to the source dir.
atp
Ah, j'ai raté ça, désolé!
Nicolas Mattia
1
si le fichier files-from a quelque chose commençant par ..rsync semble ignorer le ..me donnant une erreur comme rsync: link_stat "/home/michael/test/subdir/test.txt" failed: No such file or directory(dans ce cas, courir à partir du répertoire "test" et essayer de spécifier "../subdir/test.txt" qui existe.
Michael
L' --files-fromargument peut-il être combiné avec une liste explicite d'inclusions et d'exclusions, et les fichiers de la liste ajoutés avec --files-fromremplacer les règles d'exclusion existantes, de sorte qu'ils soient inclus s'ils apparaissent dans le fichier?
highsciguy
12

--files-from=Le paramètre nécessite une barre oblique finale si vous souhaitez conserver le chemin absolu intact. Ainsi, votre commande deviendrait quelque chose comme ci-dessous:

rsync -av --files-from=/path/to/file / /tmp/

Cela pourrait être fait comme s'il y avait un grand nombre de fichiers et que vous vouliez copier tous les fichiers vers x path. Vous trouverez donc les fichiers et lancez la sortie dans un fichier comme ci-dessous:

find /var/* -name *.log > file
Waqas Khan
la source
8

Pour mémoire, aucune des réponses ci-dessus n'a aidé, sauf une. Pour résumer, vous pouvez effectuer l'opération de sauvegarde --files-from=en utilisant soit:

 rsync -aSvuc `cat fichiers-rsync-src` / mnt / d / rsync_test /

OU

rsync -aSvuc --recursive --files-from = rsync-src-files. / mnt / d / rsync_test /

La première commande est explicite, à côté du contenu du fichier rsync-src-filesque je développerai ci-dessous. Maintenant, si vous souhaitez utiliser cette dernière version, vous devez garder à l'esprit les quatre remarques suivantes:

  1. Notez qu'il faut spécifier les deux --files-fromet le répertoire source
  2. Il faut préciser explicitement --recursive.
  3. Le fichier rsync-src-filesest un fichier créé par l'utilisateur et il a été placé dans le répertoire src pour ce test
  4. Le rsyn-src-filescontient les fichiers et dossiers à copier et ils sont pris par rapport au répertoire source. IMPORTANT: assurez-vous qu'il n'y a pas d'espaces de fin ou de lignes vides dans le fichier. Dans l'exemple ci-dessous, il n'y a que deux lignes, pas trois (déterminez-le par hasard). Le contenu de rsynch-src-filesest:

folderName1
folderName2

KF
la source
3

J'ai eu une tâche similaire: rsynchroniser tous les fichiers modifiés après une date donnée, mais en excluant certains répertoires. Il était difficile de construire un seul style de doublure tout-en-un, alors j'ai plongé le problème en plus petits morceaux. Solution finale:

find  ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | egrep -v "/\..|Downloads|FOO" > FileList.txt
rsync -v --files-from=FileList.txt ~/sourceDIR /Destination

J'utilise d'abord find -L ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS". J'ai essayé d'ajouter regexà la findligne pour exclure les modèles de nom, mais ma saveur de Linux (Mint) semble ne pas comprendre l'expression régulière de négation find. Nombre d'essais de saveurs regex - ne fonctionne pas comme souhaité. Donc, je me retrouve avec egrep -v- option qui exclut le modèle de manière simple. My rsyncne copie pas des répertoires comme /.cache ou /.config ainsi que d'autres que j'ai explicitement nommés.

Sopel
la source
1
Je pense que vous pourriez utiliser la substitution de processus pour transformer cela en une bashseule ligne:rsync -v --files-from=<(find ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | grep -Ev "/\..|Downloads|FOO") ~/sourceDIR /Destination
phk
2
$ date
  Wed 24 Apr 2019 09:54:53 AM PDT
$ rsync --version
  rsync  version 3.1.3  protocol version 31
  ...

Syntaxe: rsync <file_/_folder_list> <source> <target>

Les noms de dossier (ici, AVEC une fin /; par exemple Cancer - Evolution/) sont dans un fichier de liste de dossiers (par exemple: cm_folder_list_test):

# /mnt/Vancouver/projects/ie/claws/data/cm_folder_list_test
# test file: 2019-04-24
Cancer/
Cancer - Evolution/
Cancer - Genomic Variants/
Cancer - Metastasis (EMT Transition ...)/
Cancer Pathways, Networks/
Catabolism - Autophagy; Phagosomes; Mitophagy/
Catabolism - Lysosomes/

Si vous n'incluez pas ces /derniers, les dossiers cibles rsync'd sont créés, mais sont vides.

Ces noms de dossier sont ajoutés au reste de leur chemin ( /home/victoria/Mail/2_RESEARCH - NEWS), fournissant ainsi le chemin complet du dossier vers rsync; par exemple: /home/victoria/Mail/2_RESEARCH - NEWS/Cancer - Evolution/.

Notez que vous devez également utiliser --files-from=..., PAS --include-from=...

rsync -aqP --delete --files-from=/mnt/Vancouver/projects/ie/claws/data/cm_folder_list_test "/home/victoria/Mail/2_RESEARCH - NEWS" $IN/

(Dans mon script BASH, j'ai défini la variable $INcomme suit.)

BASEDIR="/mnt/Vancouver/projects/ie/claws"
IN=$BASEDIR/data/test/input

Options rsync utilisées:

 -a  :   archive: equals -rlptgoD (no -H,-A,-X)
    -r  :   recursive
    -l  :   copy symlinks as symlinks
    -p  :   preserve permissions
    -t  :   preserve modification times 
    -g  :   preserve group 
    -o  :   preserve owner (super-user only) 
    -D  :   same as --devices --specials 
  -q  :   quiet (/server/547106/run-totally-silent-rsync)

  --delete
    This  tells  rsync to delete extraneous files from the RECEIVING SIDE (ones
    that AREN’T ON THE SENDING SIDE), but only for the directories that are
    being synchronized.  You must have asked rsync to send the whole directory
    (e.g.  "dir" or "dir/") without using a wildcard for the directory’s contents
    (e.g. "dir/*") since the wildcard is expanded by the shell and rsync thus
    gets a request to transfer individual files, not the files’ parent directory.
    Files  that  are  excluded  from  the transfer are also excluded from being
    deleted unless you use the --delete-excluded option or mark the rules as
    only matching on the sending side (see the include/exclude modifiers in the
    FILTER RULES section).  ...
Victoria Stuart
la source
1

Cette réponse n'est pas la réponse directe à la question. Mais cela devrait vous aider à déterminer la solution la mieux adaptée à votre problème.

Lors de l'analyse du problème, vous devez activer l'option de débogage -vv

Ensuite, rsync affichera quels fichiers sont inclus ou exclus par quel modèle:

building file list ... 
[sender] hiding file FILE1 because of pattern FILE1*
[sender] showing file FILE2 because of pattern *
Matthias M
la source
0

Aucune de ces réponses n'a fonctionné pour moi, alors que je n'avais qu'une liste de répertoires . Puis je suis tombé sur la solution! Vous devez ajouter -rà --files-fromparce que -ane sera pas récursive dans ce scénario (qui savait ?!).

rsync -aruRP --files-from=directory.list . ../new/location
Théodore R. Smith
la source
Si vous indiquez «dir» dans le fichier, vous devez spécifier -r / —recursive; si vous indiquez «dir /», vous ne le faites pas.
lbutlr