Come copiare un file in più directory usando il comando gnu cp


210

È possibile copiare un singolo file in più directory usando il comando cp?

Ho provato quanto segue, che non ha funzionato:

cp file1 /foo/ /bar/
cp file1 {/foo/,/bar}

So che è possibile usare un ciclo for o find. Ma è possibile usare il comando gnu cp?

Risposte:


106

No, cppuò copiare più fonti ma verrà copiato solo su una singola destinazione. È necessario disporre di invocare cppiù volte - una volta per destinazione - per ciò che si desidera fare; usando, come dici tu, un ciclo o qualche altro strumento.


Grazie per la risposta! Ora che ci penso un po 'di più, senza flag extra (che non esistono) cp non saprò qual è la fonte e qual è la directory DEST.
Tom Feiner,

10
Questa non è la risposta corretta Si prega di vedere la risposta di Robert Gamble.
PlagueHammer,

23
@ Notturno: quale parte di ciò che ho detto è errata? Robert dà un esempio dell'uso di un altro strumento per invocare cp più volte come suggerisco. Esistono molte possibili soluzioni che implicano l'uso di altri strumenti o costrutti per farlo, ma l'OP ha indicato che era già consapevole che era possibile.
Moonshadow

2
Triste, sarebbe fantastico per cp (e scp) supportare quella funzionalità. Eppure possiamo usare tee per fare la divisione. superuser.com/questions/32630/…
Simon

4
@moonshadow: ovviamente la tua risposta è corretta. Penso che PlagueHammer voglia dire che in questo contesto l'altra risposta è più utile. Forse potresti includere qualcosa del genere anche nella tua risposta?
Tranquillo

585

Non puoi farlo da cpsolo ma puoi combinare cpcon xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

Copierà file1a dir1, dir2e dir3. xargschiamerà cp3 volte per fare questo, vedere la pagina man xargsper i dettagli.


3
Ulteriori informazioni su xargs: cyberciti.biz/faq/…
Chris Bier,

24
@Simon, come mai? "Non puoi farlo da cpsolo" Solo perché la risposta ha cercato di essere utile suggerendo un altro modo non significa che alla domanda non sia stata data risposta.
Nicole,

3
@NickC Il richiedente ha specificato: "So che è possibile usare un ciclo for o find. Ma è possibile usare il comando gnu cp?" La buona risposta è quella accettata.
Simon,

25
Stabilire che le risposte vengano accettate in base al fatto che rispondano tecnicamente alla domanda sarebbe insostenibilmente pedante e non molto utile.
Backgammon,

4
Molto utile! Per altri principianti come me: non puoi usare regex con cp, ma puoi farlo nella prima parte di questo comando (es echo dir[1-3] | xargs -n 1 cp filename.).
Jason,

77

I caratteri jolly funzionano anche con il codice Roberts

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

e l'intero commento ... Ad esempio, per spostare un file di proprietà di root (un link simbolico in realtà) che era sul mio desktop sul desktop di tutti gli utenti, per prima cosa ho dovuto sudo su (non ha funzionato diversamente) e poi ho usato: echo / home / * / Desktop / | xargs -n 1 cp -av / home / myusername / Desktop / file.
David G,

19

Per quanto posso vedere è possibile utilizzare quanto segue:

ls | xargs -n 1 cp -i file.dat

L' -iopzione di cpcomando significa che ti verrà chiesto se sovrascrivere un file nella directory corrente con il file.dat. Sebbene non sia una soluzione completamente automatica, ha funzionato per me.


1
Anche se è bene aver aggiunto la -iprotezione, questo non ti chiederà di scrivere oltre ogni file? piuttosto che copiare nelle directory?
Riccio l'

1
@Hedgehog Bene, penso che questo comando sia utile quando c'è un file nella directory e uno vuole copiarlo nelle sottodirectory della directory. In questo caso un file può essere sovrascritto una sola volta. Grazie per la tua domanda!
Evgeny

2
Per me, ha stampato una serie di cp: overwritedomande, ma non ho dovuto rispondere a nessuna di esse e non ha sovrascritto i file.
Evgeni Sergeev,

Ho anche stampato una serie di domande + copiato nel file con il nome di dir con il carattere ':' alla fine, nessuna soluzione funzionante, la soluzione di Paul funziona perfettamente
jgpATs2w

19

Vorrei utilizzare cate in teebase alle risposte che ho visto su /superuser/32630/parallel-file-copy-from-single-source-to-multiple-targets invece di cp.

Per esempio:

cat inputfile | tee outfile1 outfile2 > /dev/null

1
Un breve test che ho appena eseguito mostra che si tratta della migliore prestazione se le tue destinazioni sono unità fisiche diverse (mantenendo due copie fisiche di una base di file come il video sorgente per un film digitale).
curioso il

1
Se stai usando bash 3.0 o versioni successive, puoi usare gli intervalli come segue:cat <inputfile> | tee /path-to-files/outfile{1..4} > /dev/null
Samuel

tee < inputfile outfile1 outfile2 > /dev/nullè anche uno schema utile come mostrato dalla risposta di Taywee. Nota l'uso di io-reindirizzamento con '<' in modo che non sia necessario il piping da cat.
Alex Telon

10

Queste risposte sembrano tutte più complicate dell'ovvio:

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

un elegante e funzionante, per farlo per tutte le directory nella directory corrente, si può usarefor d in */ ; do cp $file "$i" done
FantomX1

9

ls -db di*/subdir | xargs -n 1 cp File

-bnel caso in cui sia presente uno spazio nel nome della directory, altrimenti verrà suddiviso in xargs come elemento diverso, ha avuto questo problema con la versione echo


6

Non usando cp di per sé, ma ...

Questo mi è venuto in mente nel contesto della copia di molti filmati Gopro da una (lenta) scheda SD a tre (lenta) unità USB. Volevo leggere i dati solo una volta, perché ci sono voluti per sempre. E lo volevo ricorsivo.

$ tar cf - src | tee >( cd dest1 ; tar xf - ) >( cd dest2 ; tar xf - ) | ( cd dest3 ; tar xf - )

(E puoi aggiungere più di quelle sezioni> () se vuoi più output.)

Non ne ho fatto un benchmark, ma è sicuramente molto più veloce di cp-in-a-loop (o un mucchio di invocazioni cp parallele).


5

Per utilizzare la copia con le xargsdirectory usando i caratteri jolly su Mac OS, l'unica soluzione che ha funzionato per me con spazi nel nome della directory è:

find ./fs*/* -type d -print0 | xargs -0 -n 1 cp test 

Dov'è testil file da copiare
E ./fs*/*le directory in cui copiare

Il problema è che xargs vede gli spazi come un nuovo argomento, le soluzioni per cambiare il carattere delimitatore usando -do -Epurtroppo non funziona correttamente su Mac OS.


4

Se vuoi farlo senza un comando biforcuto:

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


2

Essenzialmente equivalente alla risposta di xargs, ma nel caso in cui desideri un'esecuzione parallela:

parallel -q cp file1 ::: /foo/ /bar/

Quindi, ad esempio, per copiare file1 in tutte le sottodirectory della cartella corrente (inclusa la ricorsione):

parallel -q cp file1 ::: `find -mindepth 1 -type d`

NB: Questo probabilmente trasmette solo notevoli guadagni di velocità per casi d'uso molto specifici, ad esempio se ogni directory di destinazione è un disco distinto.

È anche funzionalmente simile all'argomento '-P' per xargs.


0

No, non puoi.

Ho scoperto in diverse occasioni che potevo usare questa funzionalità, quindi ho creato il mio strumento per farlo per me.

http://github.com/ddavison/branch

abbastanza semplice -
branch myfile dir1 dir2 dir3


Ci sono spesso scenari in cui scriverei il mio script, ma al giorno d'oggi tendo a usare così tante macchine che tenerle tutte sincronizzate sembra una seccatura maggiore. Se solo ci fosse un modo per montare una directory web cloud, ad /eesempio, solo una volta su ogni macchina, allora potrei scrivere i miei powertools e conservarli per sempre.
Evgeni Sergeev,

0
ls -d */ | xargs -iA cp file.txt A

1
Che ne dici di un po 'di spiegazione?
minuti

Questo in realtà funziona, ma una spiegazione sarebbe stata eccellente
Ælex

0

Supponiamo di voler copiare fileName.txtin tutte le sottodirectory presenti nella directory di lavoro attuale.

  1. Ottieni tutti i nomi delle sottodirectory lse salvali in alcuni file temporanei, dì:allFolders.txt

    ls > allFolders.txt
  2. Stampa l'elenco e passalo al comando xargs.

    cat allFolders.txt | xargs -n 1 cp fileName.txt

0

Un altro modo è usare cat and tee come segue:

cat <source file> | tee <destination file 1> | tee <destination file 2> [...] > <last destination file>

Penso che questo sarebbe piuttosto inefficiente, dal momento che il lavoro sarebbe suddiviso tra diversi processi (uno per destinazione) e il disco rigido dovrebbe scrivere più file contemporaneamente su diverse parti del piatto. Tuttavia, se si desidera scrivere un file su più unità diverse, questo metodo sarebbe probabilmente piuttosto efficiente (poiché tutte le copie potrebbero avvenire contemporaneamente).


0

Usando uno 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

Ho dato un voto negativo. La domanda ha chiesto specificamente una soluzione non-loop.
Alex Telon

-1

se vuoi copiare più cartelle in più cartelle, puoi fare qualcosa del genere:

echo dir1 dir2 dir3 | xargs -n 1 cp -r / path / toyourdir / {subdir1, subdir2, subdir3}


-1

Se tutte le directory di destinazione corrispondono a un'espressione di percorso, come se fossero tutte sottodirectory di path/to, utilizzare semplicemente findin combinazione con cpquesto:

find ./path/to/* -type d -exec cp [file name] {} \;

Questo è tutto.


Ho dato un voto negativo. La domanda ha chiesto specificamente una soluzione non trovabile.
Alex Telon

Grazie per essere così attento @AlexTelon. Immagino di essermi perso un po '. Spero che anche tu fossi coerente e hai dato un voto negativo a ogni altra risposta usando il findthread.
Mig82,

-2

Se devi essere specifico su quali cartelle copiare il file puoi combinare find con uno o più greps. Ad esempio per sostituire qualsiasi occorrenza di favicon.ico in qualsiasi sottocartella puoi usare:

find . | grep favicon\.ico | xargs -n 1 cp -f /root/favicon.ico

-3

Questo verrà copiato nelle sottodirectory immediate, se vuoi approfondire, regola il -maxdepthparametro.

find . -mindepth 1 -maxdepth 1 -type d| xargs -n 1 cp -i index.html

Se non si desidera copiare in tutte le directory, si spera che sia possibile filtrare le directory che non sono interessate. Esempio di copia in tutte le cartelle che iniziano con a

find . -mindepth 1 -maxdepth 1 -type d| grep \/a |xargs -n 1 cp -i index.html

Se copi in un set di directory arbitrario / disgiunto avrai bisogno del suggerimento di Robert Gamble.


-3

Mi piace copiare un file in più directory in quanto tale: cp file1 /foo/; cp file1 /bar/; cp file1 /foo2/; cp file1 /bar2/ E copiare una directory in altre directory: cp -r dir1/ /foo/; cp -r dir1/ /bar/; cp -r dir1/ /foo2/; cp -r dir1/ /bar2/

So che è come emettere diversi comandi, ma funziona bene per me quando voglio digitare 1 riga e andare via per un po '.


7
Stai rispondendo a una domanda di 6 anni con altre 15 risposte. La tua risposta deve essere piuttosto innovativa. La mia opinione - non lo è.
Craig S. Anderson,

-4

Ad esempio, se ci si trova nella directory principale delle cartelle di destinazione, è possibile eseguire:

per i in $ (ls); fare cp sourcefile $ i; fatto


La domanda dice che è possibile con un ciclo for, quindi questo non aggiunge nulla.
LJNielsenDk,

Downvoted. Non tentare mai di analizzare l'output dils e citare sempre le variabili. for i in ./*; do cp sourcefile "$i"; done
slitta,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.