Copie de fichiers parallèle d'une source unique vers plusieurs cibles?

15

J'ai plusieurs gros fichiers sur un support optique que je voudrais copier sur plusieurs cibles - dans ce cas, j'ai deux disques durs connectés au même ordinateur. Existe-t-il un utilitaire qui peut fonctionner comme:

copy source target1 target2 ... targetN
Goyuix
la source

Réponses:

23

Pour les fichiers uniques, vous pouvez utiliser teepour copier à plusieurs endroits:

cat <inputfile> | tee <outfile1> <outfile2> > <outfile3>

ou si vous préférez la version démoggifiée:

tee <outfile1> <outfile2> > <outfile3> < <inputfile>

Notez que, comme Dennis le fait remarquer dans les commentaires, teerenvoie aux stdoutfichiers répertoriés, d'où l'utilisation de la redirection pour pointer vers le fichier 3 dans les exemples ci-dessus. Vous pouvez également rediriger cela vers /dev/nullcomme ci-dessous - cela a l'avantage de garder la liste des fichiers plus cohérente sur la ligne de commande (ce qui peut faciliter le scriptage d'une solution pour un nombre variable de fichiers) mais est un peu moins efficace (bien que le la différence d'efficacité est faible: à peu près la même que la différence entre l'utilisation de la catversion ou la version sans cat):

cat <inputfile> | tee <outfile1> <outfile2> <outfile3> > /dev/null

Vous pouvez probablement combiner l'un des éléments ci-dessus avec findassez facilement pour opérer sur plusieurs fichiers dans un répertoire et moins facilement pour opérer sur des fichiers répartis sur une structure de répertoire. Sinon, vous devrez peut-être simplement désactiver les opérations de copie multiples en parallèle en tant que tâches distinctes et espérer que le cache du disque du système d'exploitation est lumineux et / ou suffisamment grand pour que chacune des tâches parallèles utilise des données de lecture mises en cache à partir de la première au lieu de provoquer une tête de lecteur raclée.

DISPONIBILITÉ: teeest couramment disponible sur les configurations Linux standard et autres systèmes unix ou similaires, généralement dans le cadre du package GNU "coreutils". Si vous utilisez Windows (votre question ne le précise pas), vous devriez le trouver dans les différents ports Windows tels que Cygwin.

INFORMATIONS SUR LA PROGRESSION: Comme la copie d'un fichier volumineux sur un support optique peut prendre un certain temps (ou sur un réseau lent, ou un fichier encore plus volumineux, même sur un support rapide local), les informations de progression peuvent être utiles. Sur la ligne de commande, j'ai tendance à utiliser le visualiseur de tuyaux (disponible dans la plupart des distributions Linux et de nombreuses collections de ports Windows et facile à compiler vous-même lorsqu'il n'est pas disponible directement) pour cela - il suffit de le remplacer catpar pvceci:

pv <inputfile> | tee <outfile1> <outfile2> > <outfile3>
David Spillett
la source
J'ai trouvé que tee.exe faisait partie du package UnxUtils. Merci pour le bon conseil!
Goyuix
5
Notez que cela teesortira également sur stdout, donc vous voudrez peut-être le faire tee outputfile1 outputfile2 < inputfile > /dev/nullcar la sortie d'un fichier binaire sur le terminal peut être bruyante et gâcher ses paramètres.
pause jusqu'à nouvel ordre.
Pour les répertoires et les fichiers multiples, utilisez simplement tar au lieu de cat. Par exempletar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
CR.
5

Pour les fenêtres:

n2ncopy fera ceci:

texte alternatif

Pour Linux:

La cpcommande seule peut copier à partir de plusieurs sources mais malheureusement pas de plusieurs destinations. Vous devrez l'exécuter plusieurs fois dans une boucle quelconque. Vous pouvez utiliser une boucle comme celle-ci et placer tous les noms de répertoire dans un fichier:

OLDIFS=$IFS
IFS=$'\n'

for line in $(cat file.txt):
do
   cp file $line
done

IFS=$OLDIFS

ou utilisez xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

Les deux vous permettront de copier des répertoires entiers / plusieurs fichiers. Ceci est également abordé dans cet article StackOverflow.

John T
la source
Le lien N2NCopy semble être rompu.
Wesley
1
Google Fu - sourceforge.net/projects/n2ncopy
Fake Name
4

Basé sur la réponse donnée pour une question similaire Une autre façon est d'utiliser GNU Parallel pour exécuter plusieurs cpinstances à la fois:

parallel -j 0 -N 1 cp file1 ::: Destination1 Destination2 Destination3

La commande ci-dessus copiera file1 dans les trois dossiers de destination en parallèle

rmiesen
la source
2

En bash (Linux, Mac ou Cygwin):

cat source | tee target1 target2 >targetN

(tee copie son entrée dans STDOUT, donc utilisez la redirection sur la dernière cible).

Sous Windows, Cygwin est souvent excessif. Au lieu de cela, vous pouvez simplement ajouter les exes du projet UnxUtils , qui incluent chat, tee et bien d'autres.

mivk
la source
1

La solution de Ryan Thompson:

for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;

a beaucoup de sens: si la vitesse d'écriture des répertoires de destination est approximativement la même, alors srcfile ne sera lu qu'une seule fois sur le disque. Le reste du temps, il sera lu dans le cache.

Je le rendrais un peu plus général, donc vous obtenez également des sous-répertoires:

for x in dest1 dest2 dest3; do cp -a srcdir $x &; done; wait;

Si la vitesse d'écriture des répertoires de destination est très différente (par exemple, l'une se trouve sur un disque RAM et l'autre sur NFS), vous pouvez voir que les parties de srcdir lues lors de la copie de srcdir vers dest1 ne sont plus dans le cache disque lors de l'écriture dest2.

Ole Tange
la source
1

Selon cette réponse: /superuser//a/1064516/702806

Une meilleure solution consiste à utiliser taret tee. La commande est plus compliquée mais tarsemble être très puissante pour le transfert ET elle n'a besoin de lire la source qu'une seule fois.

tar -c /source/dirA/ /source/file1 | tee >(cd /foo/destination3/; tar -x) >(cd /bar/destination2/; tar -x) >(cd /foobar/destination1/; tar -x) > /dev/null

Pour l'utiliser dans un script, vous devrez peut-être lancer votre script avec bash -x script.sh

Rémi Girard
la source
Marrant. Je pensais que "cela a du sens, un vote positif". A voté. Puis j'ai vérifié le lien…: D
Kamil Maciorowski
Ceci est assez clairement supérieur à la réponse (acceptée) de David Spillett si vous copiez plusieurs fichiers à la fois. Pour un fichier source unique, le seul avantage que je peux voir à ajouter tarest qu'il copiera (conservera) automatiquement les attributs de fichier (par exemple, la date / heure de modification, le mode (protection) et potentiellement les ACL, le propriétaire / groupe (si privilégié), SELinux contexte (le cas échéant), attributs étendus (le cas échéant), etc.)……………… PS Pourquoi l'utilisateur aurait-il besoin d'utiliser bash -x?
Scott
J'ai utilisé #!/bin/shau début de mon script mais la syntaxe de la commande n'est pas acceptée. Vous pouvez utiliser bash -xou #!/bin/bashau début de votre fichier. Je ne sais pas pourquoi il y a une différence entre shet les bashinterprétations.
Rémi Girard
Kamil Maciorowski - Je ne sais pas pourquoi votre réponse n'est pas votée positivement. C'est la solution parfaite. Je voulais le partager.
Rémi Girard
0

En bash:

for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;
Ryan C. Thompson
la source
2
je ne pense pas que cela fonctionnera bien. dans une copie idéalement parallèle, vous liriez une fois, en écrivant plusieurs fois. je pense que cela fera 1: 1 lit: écrit. peut-être que si les copies démarrent assez rapidement et que le cache du lecteur est suffisamment volumineux, vous n'aurez pas besoin de rechercher les têtes de lecture.
Quack Quichotte
0

Si vous souhaitez le faire dans Windows à partir de PowerShell, ce n'est pas possible par défaut, car contrairement à l' -Pathargument, le -Destinationne prend pas plusieurs arguments. Cependant, vous pouvez utiliser -Passthroughet chaîner les commandes. (Mais ce n'est pas amusant.)

La meilleure solution est de créer la vôtre, comme indiqué ici .

not2qubit
la source