Cópia de arquivo paralelo da fonte única para vários destinos?


15

Eu tenho vários arquivos grandes em mídia ótica que gostaria de copiar para vários destinos - nesse caso, tenho dois discos rígidos conectados ao mesmo computador. Existe um utilitário que pode funcionar como:

copy source target1 target2 ... targetN

Respostas:


23

Para arquivos únicos, você pode usar teepara copiar para vários locais:

cat <inputfile> | tee <outfile1> <outfile2> > <outfile3>

ou se você preferir a versão desmoggificada:

tee <outfile1> <outfile2> > <outfile3> < <inputfile>

Nota que, como aponta Dennis nos comentários teesaídas para stdout, bem como os arquivos listados, portanto, usando redirecionamento para apontar para arquivo 3 nos exemplos acima. Você também pode redirecioná-lo para /dev/nullo seguinte: isso tem a vantagem de manter a lista de arquivos mais consistente na linha de comando (o que pode facilitar a criação de scripts de uma solução para números variáveis ​​de arquivos), mas é um pouco menos eficiente (embora o a diferença de eficiência é pequena: aproximadamente a mesma diferença entre usar a catversão ou a versão sem cat):

cat <inputfile> | tee <outfile1> <outfile2> <outfile3> > /dev/null

Provavelmente, você pode combinar um dos itens acima com findbastante facilidade para operar em vários arquivos em um diretório e menos facilmente com arquivos espalhados por uma estrutura de diretórios. Caso contrário, talvez seja necessário desativar as várias operações de cópia em paralelo como tarefas separadas e esperar que o cache do disco do sistema operacional seja brilhante e / ou grande o suficiente para que cada uma das tarefas paralelas usasse dados de leitura em cache desde o início, em vez de causar a cabeça da unidade se debatendo.

DISPONIBILIDADE: teenormalmente está disponível nas configurações padrão do Linux e em outros sistemas unix ou unix, geralmente como parte do pacote "coreutils" do GNU. Se você estiver usando o Windows (sua pergunta não especifica), você deve encontrá-lo nas várias portas do Windows, como o Cygwin.

INFORMAÇÃO DE PROGRESSO: Como copiar um arquivo grande da mídia óptica pode levar algum tempo (ou em rede lenta ou um arquivo ainda maior a partir da mídia rápida local), as informações do progresso podem ser úteis. Na linha de comando que tendem a usar visualizador de tubo (disponível na maioria das distribuições Linux e muitas coleções porta do Windows e fácil de compilar-se onde não disponível diretamente) para isso - basta substituir catcom pvassim:

pv <inputfile> | tee <outfile1> <outfile2> > <outfile3>

Eu encontrei o tee.exe como parte do pacote UnxUtils. Obrigado pela ótima dica!
Goyuix

5
Observe que a teesaída também será stdout, portanto, você pode fazer isso, tee outputfile1 outputfile2 < inputfile > /dev/nullpois a saída de um arquivo binário para o terminal pode ser barulhenta e interferir nas configurações.
Pausado até novo aviso.

Para diretórios e vários arquivos, use tar em vez de cat. Por exemplotar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
CR.

5

Para Windows:

O n2ncopy fará o seguinte:

texto alternativo

Para Linux:

O cpcomando só pode copiar a partir de várias fontes, mas, infelizmente, não vários destinos. Você precisará executá-lo várias vezes em um loop de algum tipo. Você pode usar um loop assim e colocar todos os nomes de diretório em um arquivo:

OLDIFS=$IFS
IFS=$'\n'

for line in $(cat file.txt):
do
   cp file $line
done

IFS=$OLDIFS

ou use xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

Ambos permitem copiar diretórios inteiros / vários arquivos. Isso também é discutido neste artigo StackOverflow.


O link N2NCopy parece estar quebrado.
28909 Wesley


4

Baseado na resposta dada a uma pergunta semelhante Outra maneira é usar o GNU Parallel para executar várias cpinstâncias ao mesmo tempo:

parallel -j 0 -N 1 cp file1 ::: Destination1 Destination2 Destination3

O comando acima copiará o arquivo1 para todas as três pastas de destino em paralelo


2

No bash (Linux, Mac ou Cygwin):

cat source | tee target1 target2 >targetN

(tee copia sua entrada para STDOUT, portanto, use o redirecionamento no último destino).

No Windows, o Cygwin costuma ser um exagero. Em vez disso, você pode adicionar os exes do projeto UnxUtils , que incluem gato, camiseta e muitos outros.


1

A solução de Ryan Thompson:

for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;

faz muito sentido: se a velocidade de gravação dos diretórios de destino for aproximadamente a mesma, o srcfile será lido apenas uma vez no disco. O restante do tempo será lido do cache.

Eu o tornaria um pouco mais geral, para que você também tenha subdiretórios:

for x in dest1 dest2 dest3; do cp -a srcdir $x &; done; wait;

Se a velocidade de gravação dos diretórios de destino for muito diferente (por exemplo, um está em um disco ram e o outro no NFS), você poderá ver que as partes do srcdir lidas ao copiar o srcdir para dest1 não estão mais no cache do disco durante a gravação dest2.


1

De acordo com esta resposta: /superuser//a/1064516/702806

Uma solução melhor é usar tare tee. O comando é mais complicado, mas tarparece ser muito poderoso para transferência E precisa ler a fonte apenas uma vez.

tar -c /source/dirA/ /source/file1 | tee >(cd /foo/destination3/; tar -x) >(cd /bar/destination2/; tar -x) >(cd /foobar/destination1/; tar -x) > /dev/null

Para usá-lo em um script, pode ser necessário iniciar seu script com bash -x script.sh


Engraçado. Eu pensei "isso faz sentido, tenha um voto positivo". Votado. Então eu chequei o link…: D
Kamil Maciorowski

Isso é claramente superior à resposta (aceita) de David Spillett se você estiver copiando vários arquivos ao mesmo tempo. Para um único arquivo de origem, a única vantagem que posso acrescentar taré que ele copia (preserva) automaticamente os atributos do arquivo (por exemplo, data / hora da modificação, modo (proteção) e potencialmente ACLs, proprietário / grupo (se privilegiado), SELinux contexto (se aplicável), atributos estendidos (se aplicável), etc.)……………… PS Por que o usuário precisaria usar bash -x?
Scott Scott

Eu usei #!/bin/shno início do meu script, mas a sintaxe do comando não é aceita. Você pode usar bash -xou #!/bin/bashno início do seu arquivo. Não sei por que há uma diferença entre she bashinterpretações.
Rémi Girard

Kamil Maciorowski - Não sei por que sua resposta não foi votada. É a solução perfeita. Eu queria compartilhar isso.
Rémi Girard

0

Na festança:

for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;

2
Eu não acho que isso funcionará bem. em uma cópia idealmente paralela, você estaria lendo uma vez, escrevendo várias vezes. Eu acho que isso vai fazer 1: 1 lê: escreve. talvez se as cópias começarem com rapidez suficiente e o cache da unidade for grande o suficiente, você não precisará realmente procurar as cabeças de leitura.
quack quixote

0

Se você deseja fazer isso no Windows a partir do PowerShell, não é possível por padrão, porque, diferentemente do -Pathargumento, -Destinationele não recebe vários argumentos. No entanto, você pode usar -Passthroughe encadear os comandos. (Mas isso não é divertido.)

A melhor solução é criar o seu, como é mostrado aqui .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.