Як скопіювати файл у кілька каталогів за допомогою команди gnu cp


210

Чи можливо скопіювати один файл у кілька каталогів за допомогою команди cp?

Я спробував таке, що не вийшло:

cp file1 /foo/ /bar/
cp file1 {/foo/,/bar}

Я знаю, що це можливо за допомогою циклу або пошуку. Але чи можливо за допомогою команди gnu cp?

Відповіді:


106

Ні, cpможна скопіювати кілька джерел, але буде скопійовано лише в одне призначення Вам потрібно домовитись, щоб викликати cpкілька разів - один раз на місце призначення, - що ви хочете зробити; використовуючи, як ви кажете, петлю або якийсь інший інструмент.


Дякую за відповідь! Тепер, коли я подумаю про це трохи більше, без зайвих прапорів (яких не існує) cp не буде знати, що є джерелом і що таке DEST dir.
Том Фейнер

10
Це не правильна відповідь. Будь ласка, дивіться відповідь Роберта Гембла.
PlagueHammer

23
@Nocturne: яка частина сказаного мною неправильна? Роберт наводить приклад використання іншого інструменту для виклику cp кілька разів, як я пропоную. Існує багато можливих рішень, які передбачають використання інших інструментів чи конструкцій для цього, але ОП вказує, що він уже знає, що це можливо.
самогонник

2
Сумно, для cp (і scp) було б чудово підтримати цю функцію. Але ми можемо використовувати трійник для розколу. superuser.com/questions/32630/…
Саймон

4
@moonshadow: Звичайно, ваша відповідь правильна. Я думаю, що PlagueHammer хоче сказати, що в цьому контексті інша відповідь є кориснішою. Можливо, ви також можете включити щось подібне у свою відповідь?
Мирний

585

Ви не можете зробити це cpсамостійно, але ви можете комбінувати cpз xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

Буде чи копіювати file1в dir1, dir2і dir3. xargsзателефоную cp3 рази для цього, xargsдетальну інформацію див. на сторінці чоловіка .


3
Більше інформації про xargs: cyberciti.biz/faq/…
Кріс Бір

24
@Simon як так? "Ви не можете зробити це cpсамостійно" Просто тому, що відповідь намагалася бути корисною, запропонувавши інший спосіб, не означає, що на запитання не було відповіді.
Ніколь

3
@NickC Автор запитував: "Я знаю, що це можливо за допомогою циклу або знайти. Але чи можливо за допомогою команди gnu cp?" Хороша відповідь - прийнята.
Саймон

25
Сформулюючи, що відповіді слід приймати на основі того, чи технічно вони відповідають на питання, були б недостатньо педантичними та не дуже корисними.
Нарди

4
Дуже корисний! Для інших початківців, як я: ви не можете використовувати регулярний вираз з cp, але ви можете в першій частині цієї команди (наприклад, echo dir[1-3] | xargs -n 1 cp filename).
Джейсон

77

Wildcards також працюють з кодом Робертса

echo ./fs*/* | xargs -n 1 cp test 

і весь коментар ... Наприклад, для переміщення файлу, що належить корінню (насправді символьне посилання), який був на моєму робочому столі для всіх користувачів на робочому столі, спочатку я повинен був судо-су (не працював інакше), потім використовувався: ехо / головна / * / Настільний / | xargs -n 1 cp -av / home / myusername / Desktop / file.
Девід Г

19

Наскільки я бачу, ви можете використовувати наступне:

ls | xargs -n 1 cp -i file.dat

-iВаріант cpкоманди означає , що вам буде запропоновано чи перезаписати файл в поточному каталозі з file.dat. Хоча це не зовсім автоматичне рішення, воно розробило для мене.


1
Хоча добре додати -iохорону, чи не спонукає вас до написання кожного файлу? а не копіювання в каталоги?
Їжак

1
@Hedgehog Ну, я думаю, що ця команда корисна, коли в каталозі є файл, і він хоче скопіювати його в підкаталоги каталогів. У цьому випадку файл можна перезаписати лише один раз. Дякуємо за запитання!
Євгеній

2
Для мене він надрукував низку cp: overwriteзапитань, але мені не довелося відповідати ні на яке, і це не перезаписало файли.
Євгеній Сергєєв

Також надруковано серію запитань + скопійовано у файл з ім'ям dir з символом ':', наприкінці немає жодного робочого рішення, рішення Павла працює ідеально
jgpATs2w

19

Я б використовував catі teeбазувався на відповідях, які я бачив на /superuser/32630/parallel-file-copy-from-single-source-to-multiple-targets замість cp.

Наприклад:

cat inputfile | tee outfile1 outfile2 > /dev/null

1
Короткий тест, який я щойно провів, показує, що це найкращий виконавець, якщо ваші пункти призначення різні фізичні накопичувачі (зберігаючи дві фізичні копії бази файлів, як вихідне відео для цифрового фільму).
курйозер

1
Якщо ви використовуєте bash 3.0 або вище, ви можете використовувати наступні діапазони:cat <inputfile> | tee /path-to-files/outfile{1..4} > /dev/null
Самуїл

tee < inputfile outfile1 outfile2 > /dev/nullтакож є корисною схемою, як показано у відповіді Тайві. Зверніть увагу на використання йо-перенаправлення за допомогою <<, щоб трубопроводи від кішки не потрібні.
Олексій Телон

10

Усі ці відповіді здаються складнішими за очевидні:

for i in /foo /bar; do cp "$file1" "$i"; done

елегантний та робочий, зробити це для всіх каталогів у поточному for d in */ ; do cp $file "$i" done
реєстрі

9

ls -db di*/subdir | xargs -n 1 cp File

-bякщо у назві каталогу є пробіл, інакше xargs буде розбитий як інший елемент, була ця проблема з ехо-версією


6

Не використовується CP per se, але ...

Це підійшло для мене в контексті копіювання багатьох кадрів Gopro з (повільної) SD-карти на три (повільні) USB-накопичувачі. Я хотів прочитати дані лише один раз, бо це зайняло назавжди. І я хотів, щоб це було рекурсивним.

$ tar cf - src | tee >( cd dest1 ; tar xf - ) >( cd dest2 ; tar xf - ) | ( cd dest3 ; tar xf - )

(І ви можете додати більше цих розділів> (), якщо хочете отримати більше результатів.)

Я цього не орієнтував, але це, безумовно, набагато швидше, ніж cp-in-a-loop (або купа паралельних викликів cp).


5

Для використання копіювання xargsв каталоги за допомогою макетів на Mac OS, єдиним рішенням, яке працювало для мене з пробілами в імені каталогу, є:

find ./fs*/* -type d -print0 | xargs -0 -n 1 cp test 

Де testфайл, який потрібно скопіювати,
і ./fs*/*каталоги, в які потрібно скопіювати

Проблема полягає в тому, що xargs розглядає пробіли як новий аргумент, рішення для зміни символу роздільника за допомогою -dабо -E, на жаль, не працює належним чином на Mac OS.


4

Якщо ви хочете зробити це без команди, роздвоєної:

tee <inputfile file2 file3 file4 ... >/dev/null


2

По суті еквівалент відповіді xargs, але у випадку, якщо ви хочете паралельного виконання:

parallel -q cp file1 ::: /foo/ /bar/

Так, наприклад, скопіюйте файл1 у всі підкаталоги поточної папки (включаючи рекурсію):

parallel -q cp file1 ::: `find -mindepth 1 -type d`

Примітка. Це, ймовірно, передає будь-яку помітну швидкість швидкості для дуже конкретних випадків використання, наприклад, якщо кожен цільовий каталог є окремим диском.

Він також функціонально схожий на аргумент '-P' для xargs.


0

Ні, ви не можете.

Я неодноразово виявляв, що можу використовувати цю функціональність, тому створив власний інструмент для цього.

http://github.com/ddavison/branch

досить простий -
branch myfile dir1 dir2 dir3


Часто існують сценарії, коли я писав би свій власний такий сценарій, але в даний час я схильний використовувати стільки машин, що тримати їх у синхронізації здається великим клопотом. Якби тільки був спосіб встановити хмарний веб-каталог, /eнаприклад, лише один раз на кожній машині, то я міг би написати свої власні powertools і зберегти їх назавжди.
Євгеній Сергєєв

0
ls -d */ | xargs -iA cp file.txt A

1
Як щодо трохи пояснення?
хв

Це насправді працює, але пояснення було б чудовим
Æ

0

Припустимо, ви хочете скопіювати fileName.txtвсі підкаталоги в поточному робочому каталозі.

  1. Отримайте всі назви підкаталогів lsі збережіть їх у тимчасовому файлі, скажімо,allFolders.txt

    ls > allFolders.txt
  2. Роздрукуйте список і передайте його команді xargs.

    cat allFolders.txt | xargs -n 1 cp fileName.txt

0

Ще один спосіб використання котів і трійників:

cat <source file> | tee <destination file 1> | tee <destination file 2> [...] > <last destination file>

Я думаю, що це було б досить неефективно, оскільки робота буде розділена між декількома процесами (один на місце призначення), а жорсткий диск записуватиме декілька файлів одночасно в різні частини тарілки. Однак якщо ви хочете записати файл на кілька різних дисків, цей метод, ймовірно, буде досить ефективним (оскільки всі копії можуть відбуватися одночасно).


0

Використання сценарію bash

DESTINATIONPATH[0]="xxx/yyy"
DESTINATIONPATH[1]="aaa/bbb"
                ..
DESTINATIONPATH[5]="MainLine/USER"
NumberOfDestinations=6

for (( i=0; i<NumberOfDestinations; i++))
    do
        cp  SourcePath/fileName.ext ${DESTINATIONPATH[$i]}

    done
exit

Я дав це голосування. Питання спеціально задало рішення, яке не стосується циклу.
Олексій Телон

-1

якщо ви хочете скопіювати кілька папок у кілька папок, можна зробити щось подібне:

echo dir1 dir2 dir3 | xargs -n 1 cp -r / path / toyourdir / {subdir1, subdir2, subdir3}


-1

Якщо всі ваші цільові каталоги відповідають вираженню шляху - як, наприклад, всі підкаталоги, path/to- просто використовуйте findв поєднанні з cpтаким:

find ./path/to/* -type d -exec cp [file name] {} \;

Це воно.


Я дав це голосування. Питання спеціально попросило не знайти рішення.
Олексій Телон

Дякуємо за те, що ви так ретельно @AlexTelon. Я думаю, що я пропустив цей шматочок. Я сподіваюся, що ви також були послідовними, і ви дали відповідь за будь-який інший відповідь, використовуючи findв темі.
Mig82

-2

Якщо вам потрібно вказати, в які папки скопіювати файл, ви можете об'єднати пошук з одним або декількома грейпами. Наприклад, щоб замінити будь-які виникнення файлу favicon.ico в будь-якій підпапці, ви можете використовувати:

find . | grep favicon\.ico | xargs -n 1 cp -f /root/favicon.ico

-3

Це скопіює в безпосередні підкаталоги, якщо ви хочете заглибитись, відрегулюйте -maxdepthпараметр.

find . -mindepth 1 -maxdepth 1 -type d| xargs -n 1 cp -i index.html

Якщо ви не хочете копіювати у всі каталоги, сподіваємось, ви можете відфільтрувати каталоги, які вас не цікавлять. Приклад копіювання у всі папки, починаючи з a

find . -mindepth 1 -maxdepth 1 -type d| grep \/a |xargs -n 1 cp -i index.html

Якщо ви копіюєте в довільний / непересічний набір каталогів, вам знадобиться пропозиція Роберта Гембла.


-3

Мені подобається копіювати файл у кілька каталогів як такий: cp file1 /foo/; cp file1 /bar/; cp file1 /foo2/; cp file1 /bar2/ І копіювати каталог в інші каталоги: cp -r dir1/ /foo/; cp -r dir1/ /bar/; cp -r dir1/ /foo2/; cp -r dir1/ /bar2/

Я знаю, що це як видача декількох команд, але це добре працює для мене, коли я хочу набрати рядок 1 і піти на деякий час.


7
Ви відповідаєте на 6-річне запитання з 15 іншими відповідями. Ваша відповідь повинна бути досить новою. Моя думка - це не так.
Крейг С. Андерсон

-4

Наприклад, якщо ви перебуваєте в батьківській папці цільових папок, ви можете:

для i в $ (ls); зробити cp sourcefile $ i; зроблено


Питання говорить, що це можливо з циклом for, тому це дійсно нічого не додає.
LJNielsenDk

Захищений. Ніколи не намагайтеся проаналізувати вихідls , а завжди цитуйте змінні. for i in ./*; do cp sourcefile "$i"; done
sleblanc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.