Równoległa kopia pliku z jednego źródła do wielu obiektów docelowych?

15

Mam kilka dużych plików na nośniku optycznym, które chciałbym skopiować do wielu obiektów docelowych - w tym przypadku mam dwa dyski twarde podłączone do tego samego komputera. Czy istnieje narzędzie, które może działać jak:

copy source target1 target2 ... targetN
Goyuix
źródło

Odpowiedzi:

23

W przypadku pojedynczych plików możesz użyć teedo skopiowania do wielu miejsc:

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

lub jeśli wolisz wersję demoggified:

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

Zauważ, że jak Dennis wskazuje w teewynikach komentarzy, stdouta także na wymienione pliki, dlatego też w powyższych przykładach użyj przekierowania, aby wskazać plik 3. Możesz również przekierować to do /dev/nullponiższego - ma to tę zaletę, że lista plików jest bardziej spójna w wierszu poleceń (co może ułatwić skrypty rozwiązanie dla zmiennej liczby plików), ale jest nieco mniej wydajna (chociaż różnica wydajności jest niewielka: mniej więcej taka sama jak różnica między używaniem catwersji lub wersji bez cat):

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

Prawdopodobnie można połączyć jeden z powyższych z finddość łatwo operować na wielu plikach w jednym katalogu, a mniej łatwo na plikach rozproszonych w strukturze katalogów. W przeciwnym razie możesz po prostu ustawić równolegle wiele operacji kopiowania jako osobne zadania i mieć nadzieję, że pamięć podręczna dysku systemu operacyjnego jest jasna i / lub wystarczająco duża, że ​​każde z równoległych zadań używało buforowanych danych odczytu od pierwszego zamiast powodowania napędu lanie.

DOSTĘPNOŚĆ: teejest powszechnie dostępna w standardowych konfiguracjach Linuksa i innych systemach uniksowych lub podobnych, zazwyczaj jako część pakietu „coreutils” GNU. Jeśli używasz systemu Windows (twoje pytanie nie określa), powinieneś go znaleźć w różnych portach systemu Windows, takich jak Cygwin.

INFORMACJE O POSTĘPIE: Ponieważ kopiowanie dużego pliku z nośnika optycznego może zająć trochę czasu (lub w wolnej sieci lub nawet większy plik z nawet lokalnego szybkiego nośnika), informacje o postępie mogą być przydatne. W wierszu polecenia I mają tendencję do używania widza pipe (dostępny w większości dystrybucji Linuksa i wielu kolekcjach portowych Windows i łatwo samemu skompilować gdzie nie bezpośrednio) do tego - po prostu wymienić catsię pvtak:

pv <inputfile> | tee <outfile1> <outfile2> > <outfile3>
David Spillett
źródło
Znalazłem tee.exe jako część pakietu UnxUtils. Dzięki za świetną radę!
Goyuix
5
Zauważ, że teebędzie również wyprowadzany na standardowe wyjście, więc możesz to zrobić, tee outputfile1 outputfile2 < inputfile > /dev/nullponieważ wysyłanie pliku binarnego do terminala może być hałaśliwe i powodować problemy z jego ustawieniami.
Wstrzymano do odwołania.
W przypadku katalogów i wielu plików użyj tar zamiast cat. Na przykładtar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
CR.
5

Dla Windowsa:

n2ncopy zrobi to:

alternatywny tekst

W systemie Linux:

Samo cppolecenie może kopiować z wielu źródeł, ale niestety nie z wielu miejsc docelowych. Będziesz musiał uruchomić go wiele razy w jakiejś pętli. Możesz użyć takiej pętli i umieścić wszystkie nazwy katalogów w pliku:

OLDIFS=$IFS
IFS=$'\n'

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

IFS=$OLDIFS

lub użyj xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

Oba z nich pozwolą ci skopiować całe katalogi / wiele plików. Jest to również omówione w tym artykule StackOverflow.

John T.
źródło
Łącze N2NCopy wydaje się być zepsute.
Wesley,
1
Google Fu - sourceforge.net/projects/n2ncopy
Fałszywe imię
4

Na podstawie odpowiedzi udzielonej na podobne pytanie Innym sposobem jest użycie GNU Parallel do uruchamiania wielu cpinstancji jednocześnie:

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

Powyższe polecenie skopiuje plik 1 do wszystkich trzech folderów docelowych równolegle

rmiesen
źródło
2

W bash (Linux, Mac lub Cygwin):

cat source | tee target1 target2 >targetN

(tee kopiuje dane wejściowe do STDOUT, więc użyj przekierowania na ostatnim celu).

W systemie Windows Cygwin jest często przesadzony. Zamiast tego możesz po prostu dodać pliki exe z projektu UnxUtils , które obejmują cat, tee i wiele innych.

mivk
źródło
1

Rozwiązanie Ryana Thompsona:

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

ma sens: jeśli szybkość zapisu katalogów docelowych jest w przybliżeniu taka sama, plik src zostanie odczytany tylko raz z dysku. Pozostały czas będzie czytany z pamięci podręcznej.

Uczyniłbym to trochę bardziej ogólnym, więc otrzymujesz także podkatalogi:

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

Jeśli prędkość zapisu katalogów docelowych jest bardzo różna (np. Jeden znajduje się na dysku RAM, a drugi w systemie plików NFS), możesz zauważyć, że części srcdir czytają podczas kopiowania srcdir do dest1 podczas zapisywania dest2.

Ole Tange
źródło
1

Zgodnie z tą odpowiedzią: /superuser//a/1064516/702806

Lepszym rozwiązaniem jest użycie tari tee. Polecenie jest bardziej skomplikowane, ale tarwydaje się, że jest bardzo potężne do przesyłania ORAZ musi odczytać źródło tylko raz.

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

Aby użyć go w skrypcie, może być konieczne uruchomienie skryptu za pomocą bash -x script.sh

Rémi Girard
źródło
Zabawny. Pomyślałem „to ma sens, mam głos”. Pozytywne. Potem sprawdziłem link…: D
Kamil Maciorowski,
Jest to dość wyraźnie przewyższające (zaakceptowaną) odpowiedź Davida Spilletta, jeśli kopiujesz wiele plików jednocześnie. W przypadku pojedynczego pliku źródłowego jedyną zaletą, którą mogę dodać, tarjest to, że automatycznie kopiuje (zachowuje) atrybuty pliku (np. Datę / godzinę modyfikacji, tryb (ochrony) i potencjalnie listy ACL, właściciela / grupę (jeśli jest uprzywilejowana), SELinux kontekst (jeśli dotyczy), rozszerzone atrybuty (jeśli dotyczy) itp.)……………… PS Dlaczego użytkownik powinien korzystać bash -x?
Scott,
Użyłem #!/bin/shna początku skryptu, ale składnia polecenia nie jest akceptowana. Możesz użyć bash -xlub #!/bin/bashna początku swojego pliku. Nie wiem, dlaczego istnieje różnica między shi bashinterpretacje.
Rémi Girard
Kamil Maciorowski - Nie wiem, dlaczego twoja odpowiedź nie jest pozytywna. To idealne rozwiązanie. Chciałem się tym podzielić.
Rémi Girard
0

W bash:

for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;
Ryan C. Thompson
źródło
2
nie sądzę, żeby to działało dobrze. w idealnie równoległej kopii, którą czytałbyś jeden raz, pisząc wiele razy. myślę, że to zrobi 1: 1 czyta: pisze. może jeśli kopie zaczną się wystarczająco szybko, a pamięć podręczna dysku jest wystarczająco duża, nie będziesz musiał szukać głowic czytających.
quack quixote
0

Jeśli chcesz to zrobić w systemie Windows z poziomu programu PowerShell, domyślnie nie jest to możliwe, ponieważ w przeciwieństwie do -Pathargumentu, -Destinationnie przyjmuje wielu argumentów. Można jednak używać -Passthroughi łączyć szeregowo polecenia. (Ale to nie jest fajne.)

Najlepszym rozwiązaniem jest zrobienie własnego, jak pokazano tutaj .

not2qubit
źródło