Odpowiedzi:
W przypadku pojedynczych plików możesz użyć tee
do 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 tee
wynikach komentarzy, stdout
a 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/null
poniż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 cat
wersji lub wersji bez cat
):
cat <inputfile> | tee <outfile1> <outfile2> <outfile3> > /dev/null
Prawdopodobnie można połączyć jeden z powyższych z find
dość ł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ŚĆ: tee
jest 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ć cat
się pv
tak:
pv <inputfile> | tee <outfile1> <outfile2> > <outfile3>
tee
będzie również wyprowadzany na standardowe wyjście, więc możesz to zrobić, tee outputfile1 outputfile2 < inputfile > /dev/null
ponieważ wysyłanie pliku binarnego do terminala może być hałaśliwe i powodować problemy z jego ustawieniami.
tar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
Dla Windowsa:
n2ncopy zrobi to:
W systemie Linux:
Samo cp
polecenie 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.
Na podstawie odpowiedzi udzielonej na podobne pytanie Innym sposobem jest użycie GNU Parallel do uruchamiania wielu cp
instancji 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
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.
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.
Zgodnie z tą odpowiedzią: /superuser//a/1064516/702806
Lepszym rozwiązaniem jest użycie tar
i tee
. Polecenie jest bardziej skomplikowane, ale tar
wydaje 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
tar
jest 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
?
#!/bin/sh
na początku skryptu, ale składnia polecenia nie jest akceptowana. Możesz użyć bash -x
lub #!/bin/bash
na początku swojego pliku. Nie wiem, dlaczego istnieje różnica między sh
i bash
interpretacje.
W bash:
for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;
Jeśli chcesz to zrobić w systemie Windows z poziomu programu PowerShell, domyślnie nie jest to możliwe, ponieważ w przeciwieństwie do -Path
argumentu, -Destination
nie przyjmuje wielu argumentów. Można jednak używać -Passthrough
i łączyć szeregowo polecenia. (Ale to nie jest fajne.)
Najlepszym rozwiązaniem jest zrobienie własnego, jak pokazano tutaj .