Est-il possible de copier un seul fichier dans plusieurs répertoires à l'aide de la commande cp?
J'ai essayé ce qui suit, qui n'a pas fonctionné:
cp file1 /foo/ /bar/
cp file1 {/foo/,/bar}
Je sais que c'est possible en utilisant une boucle for, ou find. Mais est-ce possible d'utiliser la commande gnu cp?
Non, cp
peut copier plusieurs sources, mais uniquement dans une seule destination. Vous devez prendre des dispositions 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
Copiera file1
dans dir1
, dir2
et dir3
. xargs
appellera cp
trois fois pour ce faire. Voir la page de manuel relative à 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
Autant que je sache, 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é si vous souhaitez écraser un fichier du répertoire en cours avec le nom file.dat
. Bien que ce ne soit pas une solution complètement automatique, cela a fonctionné pour moi.
Je voudrais utiliser cat
et tee
basé sur les réponses que j'ai vu à https://superuser.com/questions/32630/parallel-file-copy-from-single-source-to -multiples-cibles au lieu de cp
.
Par exemple:
cat <inputfile> | tee <outfile1> <outfile2> > /dev/null
Ces réponses semblent toutes plus compliquées que l'évidence:
for i in /foo /bar; do cp "$file1" "$i"; done
ls -db di*/subdir | xargs -n 1 cp File
-b
dans le cas où il y a n espace dans le nom du répertoire sinon il sera cassé comme un élément différent par xargs, ce problème avec la version echo
Ne pas utiliser cp en tant que tel, mais ...
Cela m’arrivait dans le contexte de la copie d’un grand nombre de séquences Gopro d’une carte SD (lente) sur trois clés USB (lentes). Je voulais lire les données une seule fois, car cela prenait 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 évalué cela, mais c'est nettement plus rapide que cp-in-a-loop (ou un tas d'invocations cp parallèles).
Pour utiliser la copie avec xargs
dans des répertoires utilisant des caractères génériques sous Mac OS, la seule solution qui a fonctionné pour moi avec espaces dans le nom du répertoire est la suivante:
find ./fs*/* -type d -print0 | xargs -0 -n 1 cp test
Où test
est le fichier à copier
Et ./fs*/*
les répertoires vers lesquels copier
Le problème est que xargs considère les espaces comme un nouvel argument, les solutions permettant de modifier le caractère de délimitation à l'aide de -d
ou -E
ne fonctionnant malheureusement pas correctement sous Mac OS.
Si vous voulez le faire sans commande forkée:
tee <inputfile file2 file3 file4 ... >/dev/null
Essentiellement équivalente à la réponse xargs, mais si vous voulez une exécution parallèle:
parallel -q cp file1 ::: /foo/ /bar/
Ainsi, par exemple, pour copier fichier1 dans tous les sous-répertoires du dossier actuel (y compris la récursivité):
parallel -q cp file1 ::: `find -mindepth 1 -type d`
NB: Cela ne traduit 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 également fonctionnellement similaire à l'argument '-P' pour xargs.
Utiliser 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
ls -d */ | xargs -iA cp file.txt A
Supposons que vous souhaitiez 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 transmettez-la à la commande xargs
.
cat allFolders.txt | xargs -n 1 cp fileName.txt
Non vous ne pouvez pas.
J'ai trouvé à plusieurs reprises que je pouvais utiliser cette fonctionnalité et j'ai donc créé mon propre outil pour le faire à ma place.
http://github.com/ddavison/branch
assez simple -branch myfile dir1 dir2 dir3
Une autre méthode consiste à utiliser le chat et le tee comme suit:
cat <source file> | tee <destination file 1> | tee <destination file 2> [...] > <last destination file>
Je pense cependant que cela 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 (toutes les copies pouvant être effectuées simultanément).
Si tous vos répertoires cibles correspondent à une expression de chemin - comme s'ils étaient tous des sous-répertoires de path/to
-, utilisez simplement find
en combinaison avec cp
comme ceci:
find ./path/to/* -type d -exec cp [file name] {} \;
C'est ça.