web-dev-qa-db-fra.com

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 à 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?

199
Tom Feiner

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.

103
moonshadow

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.

568
Robert Gamble

Les caractères génériques fonctionnent également avec le code Roberts

echo ./fs*/* | xargs -n 1 cp test 
76
Paul

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.

19
Evgeny

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
17
deterb

Ces réponses semblent toutes plus compliquées que l'évidence:

for i in /foo /bar; do cp "$file1" "$i"; done
9
Waxrat

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

9
thAAAnos

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).

6
oggust

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 

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.

4
MegaCookie

Si vous voulez le faire sans commande forkée:

tee <inputfile file2 file3 file4 ... >/dev/null

3
Taywee

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.

2
alainv

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
1
Patrick Manley
ls -d */ | xargs -iA cp file.txt A
0
Sj Lee

Supposons que vous souhaitiez copier fileName.txt dans tous les sous-répertoires du répertoire de travail actuel.

  1. Obtenez tous les noms de sous-répertoires via ls et enregistrez-les dans un fichier temporaire, par exemple, allFolders.txt.

    ls > allFolders.txt
    
  2. Imprimez la liste et transmettez-la à la commande xargs.

    cat allFolders.txt | xargs -n 1 cp fileName.txt
    
0
Devendra Lattu

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

0
ddavison

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).

0
user168046

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.

0
Mig82