Паралельна копія файлу з одного джерела на кілька цілей?


14

У мене є кілька великих файлів на оптичному носії, які я хотів би скопіювати на кілька цілей - у цьому випадку у мене на одному комп’ютері приєднано два жорстких диска. Чи є утиліта, яка може функціонувати як:

copy source target1 target2 ... targetN

Відповіді:


22

Для одиночних файлів можна teeскопіювати в декілька місць:

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

або якщо ви віддаєте перевагу демогіфікованій версії:

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

Зауважте, що, як вказує Денніс у коментарях, teeвиводиться stdoutяк і перелічені файли, отже, використовуючи перенаправлення, щоб вказати на файл 3 у наведених вище прикладах. Ви також можете перенаправити це на /dev/nullнаступне - це має перевагу в тому, щоб список команд був більш послідовним у командному рядку (що може полегшити сценарій рішення для змінної кількості файлів), але є трохи менш ефективним (хоча Різниця в ефективності невелика: приблизно така ж, як і різниця між використанням catверсії або версії без cat):

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

Можливо, ви могли б поєднати одне з вищезазначених з findдосить легким для роботи з декількома файлами в одному каталозі і менш легким для роботи з файлами, рознесеними по структурі каталогу. В іншому випадку вам може просто доведеться паралельно відключати кілька операцій копіювання як окремі завдання, і сподіваєтесь, що кеш диска ОС яскравий і / або достатньо великий, щоб кожна з паралельних завдань, що використовуються в кешеному режимі, читала дані з першого, а не викликала головку диска. молоть.

НАЛИЧНІСТЬ: teeзазвичай доступна в стандартних установках Linux та інших unix або unix-подібних системах, як правило, як частина пакету GNU "coreutils". Якщо ви використовуєте Windows (у вашому питанні не вказано), ви повинні знайти її в різних портах Windows, таких як Cygwin.

ІНФОРМАЦІЯ ПРО ПРОГРЕС: Оскільки копіювання великого файлу з оптичного носія може зайняти деякий час (або через повільну мережу, або ще більший файл з навіть локальних швидких медіа), інформація про прогрес може бути корисною. У командному рядку я вважаю за краще використовувати глядач труби (доступний в більшості Linux дистрибутивів і багатьох колекціях портів для Windows і легко скомпілювати себе , де не доступні безпосередньо) для цього - просто замінити catз pvнаступним чином:

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

Я виявив, що tee.exe є частиною пакету UnxUtils. Дякую за чудову пораду!
Гойукс

5
Зверніть увагу, що teeтакож буде виводитися у stdout, тому ви, можливо, захочете це зробити, tee outputfile1 outputfile2 < inputfile > /dev/nullоскільки виведення бінарного файлу в термінал може бути галасливим і безладним з його налаштуваннями.
Денніс Вільямсон

Для каталогів та декількох файлів просто використовуйте tar, а не cat. Наприкладtar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
CR.

5

Для Windows:

n2ncopy зробить це:

alt текст

Для Linux:

cpКоманда тільки може скопіювати з декількох джерел , але , до жаль , НЕ різних напрямків. Вам потрібно буде запустити його кілька разів у певному циклі. Ви можете використовувати цикл, як так, і розмістити всі назви каталогів у файлі:

OLDIFS=$IFS
IFS=$'\n'

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

IFS=$OLDIFS

або використовувати xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

І те й інше дозволить вам копіювати цілі каталоги / кілька файлів. Про це також йдеться в цій статті StackOverflow.


Здається, посилання N2NCopy розірвано.
Веслі


4

Виходячи з відповіді, наданої на аналогічне запитання Ще одним способом є використання GNU Parallel для запуску декількох cpпримірників одночасно:

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

Вищевказана команда буде копіювати файл1 у всі три цільові папки паралельно


2

В bash (Linux, Mac або Cygwin):

cat source | tee target1 target2 >targetN

(трійник копіює вхід до STDOUT, тому використовуйте перенаправлення на останню ціль).

У Windows Cygwin часто надмірний. Натомість ви можете просто додати exe з проекту UnxUtils , до якого входять кішки, трійники та багато інших.


1

Рішення Райана Томпсона:

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

має багато сенсу: Якщо швидкість запису в цілях призначення dirs приблизно однакова, то srcfile буде прочитаний лише один раз з диска. Решту часу він буде читатися з кеша.

Я б зробив це трохи більш загальним, тому ви також отримаєте підкаталоги:

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

Якщо швидкість запису dest dirs сильно відрізняється (наприклад, одна знаходиться на операційному диску, а інша на NFS), то ви можете побачити, що частини srcdir, прочитані під час копіювання srcdir в dest1, більше не зберігаються в кеш-диску диска під час запису dest2.


1

Відповідно до цієї відповіді: https://superuser.com/a/1064516/702806

Кращим рішенням є використання tarта tee. Команда є більш складною, але tarздається, що вона дуже потужна для передачі І їй потрібно прочитати джерело лише один раз.

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

Щоб використовувати його в сценарії, можливо, вам доведеться запустити свій скрипт bash -x script.sh


Смішно. Я подумав, що "це має сенс, є підтримка". Отримано. Тоді я перевірив посилання…: D
Каміль Маціоровський

Це досить явно перевершує відповідь Девіда Спіллета, якщо ви копіюєте відразу декілька файлів. Для єдиного вихідного файлу єдиною перевагою, яку я бачу додати, tarє те, що він автоматично копіює (зберігає) атрибути файлу (наприклад, дата / час модифікації, режим (захист) та потенційно ACL, власник / група (якщо привілейовано), SELinux контекст (якщо застосовується), розширені атрибути (якщо застосовується) тощо)……………… PS Навіщо користувачеві потрібно використовувати bash -x?
Скотт

Я використовував #!/bin/shна початку свого сценарію, але синтаксис команди не приймається. Ви можете використовувати bash -xабо #!/bin/bashна початку свого файлу. Я не знаю, чому є різниця між shта bashінтерпретаціями.
Ремі Жирар

Каміль Маціоровський - Я не знаю, чому ваша відповідь не схвалюється. Це ідеальне рішення. Я хотів поділитися цим.
Ремі Жирард

0

В bash:

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

2
я не думаю, що це буде добре. в ідеально паралельній копії, яку ви читали один раз, пишете багато разів. Я думаю, що це буде 1: 1 читає: пише. можливо, якщо копії запускаються досить швидко, а кеш-пам'ять накопичувача досить велика, вам насправді не потрібно буде шукати прочитані голови.
шарлатаний кіхот
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.