Comment copier un fichier dans plusieurs répertoires à l'aide de la commande gnu cp
Est-il possible de copier un seul fichier dans plusieurs répertoires en utilisant la commande cp ?
J'ai essayé ce qui suit, qui n'a pas fonctionné:
cp file1 /foo/ /bar/
cp file1 {/foo/,/bar}
Je sais qu'il est possible d'utiliser une boucle for, ou find. Mais est-ce possible en utilisant la commande gnu cp?
21 réponses
Non, cp
peut copier plusieurs sources mais ne copiera que vers une seule destination. Vous devez vous arranger pour appeler cp
plusieurs fois-une fois par destination - pour ce que vous voulez faire; en utilisant, comme vous le dites, une boucle ou un autre outil.
, Vous ne pouvez pas faire cela avec cp
seul, mais vous pouvez combiner cp
avec xargs
:
echo dir1 dir2 dir3 | xargs -n 1 cp file1
Copie file1
pour dir1
, dir2
, et dir3
. xargs
appellera cp
3 fois pour ce faire, voir la page de man pour xargs
pour plus de détails.
Les caractères génériques fonctionnent également avec le code Roberts
echo ./fs*/* | xargs -n 1 cp test
Pour autant que je puisse le voir, vous pouvez utiliser ce qui suit:
ls | xargs -n 1 cp -i file.dat
L'option -i
de la commande cp
signifie qu'il vous sera demandé de remplacer un fichier dans le répertoire courant par file.dat
. Bien que ce ne soit pas une solution complètement automatique, cela a fonctionné pour moi.
J'utiliserais cat
et tee
en fonction des réponses que j'ai vues à https://superuser.com/questions/32630/parallel-file-copy-from-single-source-to-multiple-targets au lieu de cp
.
Par exemple:
cat <inputfile> | tee <outfile1> <outfile2> > /dev/null
ls -db di*/subdir | xargs -n 1 cp File
-b
dans le cas où il y a un espace dans le nom du répertoire sinon il sera cassé comme un élément différent par xargs, a eu ce problème avec la version echo
Ces réponses semblent toutes plus compliquées que l'évidence:
for i in /foo /bar; do cp "$file1" "$i"; done
Ne pas utiliser cp en soi, mais...
Cela m'est venu dans le contexte de la copie de beaucoup de séquences Gopro sur une carte SD (lente) sur trois lecteurs USB (lents). Je voulais lire les données une seule fois, parce que cela a pris une éternité. Et je le voulais récursif.
$ tar cf - src | tee >( cd dest1 ; tar xf - ) >( cd dest2 ; tar xf - ) | ( cd dest3 ; tar xf - )
(et vous pouvez ajouter plus de ces sections > () si vous voulez plus de sorties.)
Je n'ai pas comparé cela, mais c'est certainement beaucoup plus rapide que cp-in-a-loop (ou un tas d'invocations CP parallèles).
Si vous voulez le faire sans une commande fourchue:
tee <inputfile file2 file3 file4 ... >/dev/null
Pour utiliser la copie avec xargs
dans les répertoires à l'aide de caractères génériques sur Mac OS, la seule solution qui a fonctionné pour moi avec Espaces Dans le nom du répertoire est:
find ./fs*/* -type d -print0 | xargs -0 -n 1 cp test
Où test
est le fichier à copier
Et ./fs*/*
les répertoires à copier dans
Le problème est que xargs voit les espaces comme un nouvel argument, les solutions pour changer le caractère de délimiteur en utilisant -d
ou -E
ne fonctionnent malheureusement pas correctement sur Mac OS.
Essentiellement équivalent à la réponse xargs, mais au cas où vous souhaiteriez une exécution parallèle:
parallel -q cp file1 ::: /foo/ /bar/
Ainsi, par exemple, pour copier file1 dans tous les sous-répertoires du dossier courant (y compris la récursivité):
parallel -q cp file1 ::: `find -mindepth 1 -type d`
N.B.: cela ne transmet probablement que des gains de vitesse notables pour des cas d'utilisation très spécifiques, par exemple si chaque répertoire cible est un disque distinct.
Il est aussi fonctionnellement similaire à l'argument'- P ' pour xargs.
Non - vous ne pouvez pas.
J'ai trouvé à plusieurs reprises que je pouvais utiliser cette fonctionnalité, donc j'ai fait mon propre outil pour le faire pour moi.
Http://github.com/ddavison/branch
Assez simple -branch myfile dir1 dir2 dir3
Supposons que vous vouliez copier fileName.txt
dans tous les sous-répertoires du répertoire de travail actuel.
-
Obtenez tous les noms de sous-répertoires via
ls
et enregistrez-les dans un fichier temporaire par exemple,allFolders.txt
ls > allFolders.txt
-
Imprimez la liste et passez-la à la commande
xargs
.cat allFolders.txt | xargs -n 1 cp fileName.txt
Une autre façon est d'utiliser cat et tee comme suit:
cat <source file> | tee <destination file 1> | tee <destination file 2> [...] > <last destination file>
Je pense que ce serait assez inefficace, car le travail serait divisé en plusieurs processus (un par destination) et le disque dur écrirait plusieurs fichiers à la fois sur différentes parties du plateau. Cependant, si vous vouliez écrire un fichier sur plusieurs lecteurs différents, cette méthode serait probablement assez efficace (car toutes les copies pourraient se produire simultanément).
Utilisation d'un script bash
DESTINATIONPATH[0]="xxx/yyy"
DESTINATIONPATH[1]="aaa/bbb"
..
DESTINATIONPATH[5]="MainLine/USER"
NumberOfDestinations=6
for (( i=0; i<NumberOfDestinations; i++))
do
cp SourcePath/fileName.ext ${DESTINATIONPATH[$i]}
done
exit
Si vous voulez copier plusieurs dossiers sur plusieurs dossiers on peut faire quelque chose comme ceci:
Echo dir1 dir2 dir3 | xargs-n 1 cp-R /path/toyourdir/{subdir1, subdir2, subdir3}
Si vous devez être précis sur les dossiers dans lesquels copier le fichier, vous pouvez combiner find avec un ou plusieurs greps. Par exemple pour remplacer toutes les occurrences de favicon.ico dans n'importe quel sous-dossier que vous pouvez utiliser:
find . | grep favicon\.ico | xargs -n 1 cp -f /root/favicon.ico
Cela va copier dans les sous-répertoires immédiats, si vous voulez aller plus loin, ajustez le paramètre -maxdepth
.
find . -mindepth 1 -maxdepth 1 -type d| xargs -n 1 cp -i index.html
Si vous ne voulez pas copier dans tous les répertoires, espérons que vous pouvez filtrer les répertoires qui ne vous intéressent pas. Exemple de copie dans tous les dossiers commençant par a
find . -mindepth 1 -maxdepth 1 -type d| grep \/a |xargs -n 1 cp -i index.html
Si vous copiez dans un ensemble de répertoires arbitraire/disjoint, vous aurez besoin de la suggestion de Robert Gamble.
J'aime copier un fichier dans plusieurs répertoires en tant que tel:
cp file1 /foo/; cp file1 /bar/; cp file1 /foo2/; cp file1 /bar2/
Et copier un répertoire dans d'autres répertoires:
cp -r dir1/ /foo/; cp -r dir1/ /bar/; cp -r dir1/ /foo2/; cp -r dir1/ /bar2/
Je sais que c'est comme émettre plusieurs commandes, mais cela fonctionne bien pour moi quand je veux taper 1 ligne et partir pendant un moment.
Par exemple, si vous êtes dans le répertoire parent de vos dossiers de destination, vous pouvez faire:
For i in $(ls); do CP sourcefile $i; done