Параллельное копирование файла из одного источника в несколько целей?

15

У меня есть несколько больших файлов на оптическом носителе, которые я хотел бы скопировать в несколько целей - в этом случае у меня есть два жестких диска, подключенных к одному компьютеру. Есть ли утилита, которая может функционировать как:

copy source target1 target2 ... targetN
Goyuix
источник

Ответы:

23

Для отдельных файлов вы можете использовать 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-подобных системах, обычно в составе пакета «coreutils» GNU. Если вы используете Windows (ваш вопрос не указан), вы должны найти его в различных портах Windows, таких как Cygwin.

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

pv <inputfile> | tee <outfile1> <outfile2> > <outfile3>
Дэвид Спиллетт
источник
Я обнаружил, что tee.exe является частью пакета UnxUtils. Спасибо за отличный совет!
Goyuix
5
Обратите внимание, что teeэто также приведет к выводу на стандартный вывод, так что вы можете захотеть это сделать, tee outputfile1 outputfile2 < inputfile > /dev/nullпоскольку вывод двоичного файла на терминал может быть шумным и мешать его настройкам.
Приостановлено до дальнейшего уведомления.
Для каталогов и нескольких файлов просто используйте tar вместо cat. Напримерtar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
кр.
5

Для Windows:

n2ncopy сделает это:

альтернативный текст

Для 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 ссылка, кажется, не работает.
Уэсли
1
Google Fu - sourceforge.net/projects/n2ncopy
Фальшивое имя
4

Исходя из ответа на аналогичный вопрос Другой способ - использовать GNU Parallel для одновременного запуска нескольких cpэкземпляров:

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

Приведенная выше команда копирует file1 во все три папки назначения параллельно

rmiesen
источник
2

В bash (Linux, Mac или Cygwin):

cat source | tee target1 target2 >targetN

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

В Windows Cygwin часто бывает излишним. Вместо этого вы можете просто добавить exe- файлы из проекта UnxUtils , которые включают cat, tee и многие другие.

mivk
источник
1

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

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

имеет большой смысл: если скорость записи целевых каталогов примерно одинакова, то srcfile будет считан с диска только один раз. В остальное время он будет читаться из кеша.

Я бы сделал это немного более общим, поэтому вы также получите подкаталоги:

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

Если скорость записи папок dest очень различна (например, одна находится на оперативном диске, а другая - в NFS), то вы можете увидеть, что части чтения srcdir при копировании srcdir в dest1 больше не находятся в кеше диска при записи dest2.

Оле Танге
источник
1

Согласно этому ответу: /superuser//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

Реми Жирар
источник
Смешной. Я думал, что "это имеет смысл, есть голос". Upvoted. Тогда я проверил ссылку…: D
Камиль Мачоровский
Это довольно явно превосходит (принятый) ответ Дэвида Спиллета, если вы копируете несколько файлов одновременно. Для одного исходного файла я вижу только одно преимущество в tarтом, что он автоматически копирует (сохраняет) атрибуты файла (например, дату / время изменения, режим (защита) и, возможно, списки ACL, владелец / группу (если есть привилегии), SELinux контекст (если применимо), расширенные атрибуты (если применимо) и т. д.) ………………… PS Зачем пользователю использовать bash -x?
Скотт
Я использовал #!/bin/shв начале моего сценария, но синтаксис команды не принят. Вы можете использовать bash -xили #!/bin/bashв начале вашего файла. Я не знаю , почему существует разница между shи bashинтерпретации.
Реми Жирар
Камиль Мачоровски - я не знаю, почему ваш ответ не проголосовал. Это идеальное решение. Я хотел поделиться этим.
Реми Жирар
0

В Баш:

for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;
Райан К. Томпсон
источник
2
Я не думаю, что это будет хорошо работать. в идеально параллельной копии вы будете читать один раз, писать много раз. Я думаю, что это будет делать 1: 1 читает: пишет. возможно, если копии запускаются достаточно быстро и кеш диска достаточно велик, вам не нужно искать головки чтения.
Квик-кихот
0

Если вы хотите сделать это в Windows из PowerShell, это невозможно по умолчанию, поскольку в отличие от -Pathаргумента, -Destinationон не принимает несколько аргументов. Однако вы можете использовать -Passthroughи последовательно соединять команды. (Но это не весело.)

Лучшее решение - сделать свое, как показано здесь .

not2qubit
источник