Risposte:
Per i singoli file è possibile utilizzare tee
per copiare in più posizioni:
cat <inputfile> | tee <outfile1> <outfile2> > <outfile3>
o se preferisci la versione ridotta:
tee <outfile1> <outfile2> > <outfile3> < <inputfile>
Si noti che, come sottolinea Dennis nei commenti, vengono tee
emessi stdout
anche i file elencati, quindi utilizzando il reindirizzamento per puntare al file 3 negli esempi precedenti. Potresti anche reindirizzare questo /dev/null
come di seguito: questo ha il vantaggio di mantenere l'elenco dei file più coerente sulla riga di comando (che potrebbe rendere più semplice lo scripting di una soluzione per un numero variabile di file) ma è un po 'meno efficiente (sebbene il la differenza di efficienza è piccola: quasi uguale alla differenza tra l'utilizzo della cat
versione o della versione senza cat
):
cat <inputfile> | tee <outfile1> <outfile2> <outfile3> > /dev/null
Probabilmente potresti combinare uno dei precedenti con find
abbastanza facilmente operare su più file in una directory e meno facilmente operare su file distribuiti su una struttura di directory. Altrimenti potresti dover semplicemente impostare le operazioni multiple di copia in parallelo come attività separate e sperare che la cache del disco del sistema operativo sia luminosa e / o abbastanza grande da far sì che ciascuna delle attività parallele utilizzi i dati di lettura memorizzati nella cache dal primo invece di causare testata botte.
DISPONIBILITÀ: tee
è comunemente disponibile su configurazioni Linux standard e altri sistemi unix o unix-like, di solito come parte del pacchetto "coreutils" GNU. Se stai usando Windows (la tua domanda non specifica), dovresti trovarlo nelle varie porte di Windows come Cygwin.
INFORMAZIONI SUL PROGRESSO: Dal momento che la copia di un file di grandi dimensioni da supporti ottici può richiedere del tempo (o su una rete lenta o un file ancora più grande anche da un supporto veloce locale), le informazioni sullo stato di avanzamento possono essere utili. Sulla riga di comando tendo a usare il visualizzatore di pipe (disponibile nella maggior parte delle distribuzioni Linux e in molte raccolte di porte Windows e facile da compilare laddove non disponibile direttamente) per questo - basta sostituirlo cat
con pv
così:
pv <inputfile> | tee <outfile1> <outfile2> > <outfile3>
tee
verrà anche emesso su stdout, quindi potresti voler fare tee outputfile1 outputfile2 < inputfile > /dev/null
poiché l'output di un file binario sul terminale potrebbe essere rumoroso e incasinato con le sue impostazioni.
tar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
Per Windows:
n2ncopy farà questo:
Per Linux:
Il cp
comando da solo può copiare da più origini ma sfortunatamente non più destinazioni. Dovrai eseguirlo più volte in un ciclo di qualche tipo. È possibile utilizzare un ciclo in questo modo e posizionare tutti i nomi di directory in un file:
OLDIFS=$IFS
IFS=$'\n'
for line in $(cat file.txt):
do
cp file $line
done
IFS=$OLDIFS
o usa xargs:
echo dir1 dir2 dir3 | xargs -n 1 cp file1
Entrambi permetteranno di copiare intere directory / file multipli. Questo è anche discusso in questo articolo StackOverflow.
Basato sulla risposta fornita per una domanda simile Un altro modo è usare GNU Parallel per eseguire più cp
istanze contemporaneamente:
parallel -j 0 -N 1 cp file1 ::: Destination1 Destination2 Destination3
Il comando sopra copierà file1 in tutte e tre le cartelle di destinazione in parallelo
In bash (Linux, Mac o Cygwin):
cat source | tee target1 target2 >targetN
(Tee copia il suo input su STDOUT, quindi usa il reindirizzamento sull'ultimo target).
In Windows, Cygwin è spesso eccessivo. Invece, puoi semplicemente aggiungere gli ex dal progetto UnxUtils , che includono cat, tee e molti altri.
La soluzione di Ryan Thompson:
for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;
ha molto senso: se la velocità di scrittura delle directory di destinazione è approssimativamente la stessa, allora srcfile verrà letto una sola volta dal disco. Il resto del tempo verrà letto dalla cache.
Lo renderei un po 'più generale, quindi otterrai anche i sottodir:
for x in dest1 dest2 dest3; do cp -a srcdir $x &; done; wait;
Se la velocità di scrittura delle directory dest è molto diversa (ad esempio, una è su un disco ram e l'altra su NFS), è possibile che le parti di srcdir vengano lette durante la copia di srcdir in dest1 non si trovino più nella cache del disco durante la scrittura dest2.
Secondo questa risposta: /superuser//a/1064516/702806
Una soluzione migliore è usare tar
e tee
. Il comando è più complicato ma tar
sembra essere molto potente per il trasferimento E deve leggere la fonte solo una volta.
tar -c /source/dirA/ /source/file1 | tee >(cd /foo/destination3/; tar -x) >(cd /bar/destination2/; tar -x) >(cd /foobar/destination1/; tar -x) > /dev/null
Per usarlo in uno script, potrebbe essere necessario avviare lo script con bash -x script.sh
tar
è che copierà automaticamente (preserva) gli attributi del file (ad es. Data / ora di modifica, modalità (protezione) e potenzialmente ACL, proprietario / gruppo (se privilegiato), SELinux contesto (se applicabile), attributi estesi (se applicabile), ecc.) ... ... ... ... ... ... PS Perché l'utente dovrebbe utilizzare bash -x
?
#!/bin/sh
all'inizio del mio script ma la sintassi del comando non è stata accettata. Puoi usare bash -x
o #!/bin/bash
all'inizio del tuo file. Non so perché ci sia una differenza tra sh
e bash
interpretazioni.
In bash:
for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;
Se vuoi farlo in Windows da PowerShell, non è possibile per impostazione predefinita, perché a differenza -Path
dell'argomento, -Destination
non accetta più argomenti. Tuttavia, è possibile utilizzare -Passthrough
e collegare a catena i comandi. (Ma non è divertente.)
La soluzione migliore è crearne una tua, come mostrato qui .