Cách sao chép một tập tin vào nhiều thư mục bằng lệnh gnu cp


210

Có thể sao chép một tập tin vào nhiều thư mục bằng lệnh cp không?

Tôi đã thử cách sau, không được:

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

Tôi biết có thể sử dụng vòng lặp for hoặc tìm. Nhưng nó có thể sử dụng lệnh gnu cp không?

Câu trả lời:


106

Không, cpcó thể sao chép nhiều nguồn nhưng sẽ chỉ sao chép vào một đích duy nhất. Bạn cần sắp xếp để gọi cpnhiều lần - một lần cho mỗi điểm đến - cho những gì bạn muốn làm; sử dụng, như bạn nói, một vòng lặp hoặc một số công cụ khác.


Cảm ơn câu trả lời! Bây giờ tôi nghĩ về nó nhiều hơn một chút, không có cờ bổ sung (không tồn tại) cp sẽ không biết nguồn nào là gì và thư mục DEST là gì.
Tom Feiner

10
Đây không phải là câu trả lời chính xác. Xin vui lòng xem câu trả lời của Robert Gamble.
Bệnh dịch hạch

23
@Nocturne: phần nào trong những gì tôi nói là không chính xác? Robert đưa ra một ví dụ về việc sử dụng một công cụ khác để gọi cp nhiều lần như tôi đề xuất. Có nhiều giải pháp khả thi liên quan đến việc sử dụng các công cụ hoặc cấu trúc khác để làm điều đó, nhưng OP đã chỉ ra rằng anh ấy đã nhận thức được điều đó là có thể.
trăng

2
Đáng buồn thay, thật tuyệt vời khi cp (và scp) hỗ trợ tính năng đó. Tuy nhiên, chúng ta có thể sử dụng tee để phân chia. superuser.com/questions/32630/ấc
Simon

4
@moonshadow: Tất nhiên câu trả lời của bạn là chính xác. Tôi nghĩ Plague Hammer muốn nói rằng trong bối cảnh này, câu trả lời khác hữu ích hơn. Có lẽ bạn có thể bao gồm một cái gì đó như thế trong câu trả lời của bạn quá?
Hòa bình

585

Bạn không thể làm điều này với cpmột mình nhưng bạn có thể kết hợp cpvới xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

Sẽ sao chép file1đến dir1, dir2dir3. xargssẽ gọi cp3 lần để làm điều này, xem trang man xargsđể biết chi tiết.


3
Thông tin thêm về xargs: cyberciti.biz/faq/ Kẻ
Chris Bier

24
@Simon thế nào? "Bạn không thể làm điều này cpmột mình" Chỉ vì câu trả lời cố gắng hữu ích bằng cách đề xuất một cách khác không có nghĩa là câu hỏi không được trả lời.
Nicole

3
@NickC Người hỏi đã chỉ định: "Tôi biết có thể sử dụng vòng lặp for hoặc find. Nhưng có thể sử dụng lệnh gnu cp không?" Câu trả lời tốt là một trong những chấp nhận.
Simon

25
Quy định rằng các câu trả lời được chấp nhận dựa trên việc họ trả lời về mặt kỹ thuật câu hỏi có mang tính mô phạm không thể vượt qua và không thực sự hữu ích.
Backgammon

4
Rất hữu ích! Đối với những người mới bắt đầu như tôi: bạn không thể sử dụng regex với cp, nhưng bạn có thể trong phần đầu của lệnh này (ví dụ echo dir[1-3] | xargs -n 1 cp filename).
Jason

77

Ký tự đại diện cũng hoạt động với mã Roberts

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

và toàn bộ nhận xét ... Ví dụ: để di chuyển tệp thuộc sở hữu gốc (thực tế là một liên kết tượng trưng) trên máy tính để bàn của tôi sang tất cả máy tính để bàn của người dùng, trước tiên tôi phải sudo su (không hoạt động khác) sau đó sử dụng: echo / home / * / Máy tính để bàn / | xargs -n 1 cp -av / home / myusername / Desktop / file.
David G

19

Theo như tôi có thể thấy, bạn có thể sử dụng như sau:

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

Các -itùy chọn cpphương tiện lệnh đó bạn sẽ được hỏi có ghi đè lên một tập tin trong thư mục hiện hành với file.dat. Mặc dù nó không phải là một giải pháp hoàn toàn tự động, nó đã giúp ích cho tôi.


1
Mặc dù thật tốt khi có thêm người -ibảo vệ, bạn sẽ không nhắc bạn về việc viết mỗi tệp chứ? thay vì sao chép vào các thư mục?
Nhím

1
@Hedgehog Vâng, tôi nghĩ rằng lệnh này hữu ích khi có một tệp trong thư mục và người ta muốn sao chép nó vào thư mục con của thư mục. Trong trường hợp này, một tập tin có thể được ghi đè chỉ một lần. Cảm ơn câu hỏi của bạn!
Evgeny

2
Đối với tôi, nó đã in một loạt các cp: overwritecâu hỏi, nhưng tôi không phải trả lời bất kỳ câu hỏi nào và nó không ghi đè lên các tập tin.
Evgeni Sergeev

Đồng thời in một loạt câu hỏi + được sao chép vào tệp có tên dir với ký tự ':' ở cuối, không có giải pháp nào hoạt động cả, giải pháp của Paul đang hoạt động hoàn hảo
jgpATs2w

19

Tôi sẽ sử dụng catteedựa trên các câu trả lời tôi thấy tại /superuser/32630/pool-file-copy-from-single-source-to-multipl-target thay vì cp.

Ví dụ:

cat inputfile | tee outfile1 outfile2 > /dev/null

1
Một bài kiểm tra chữ thảo tôi vừa thực hiện cho thấy đây là trình diễn tốt nhất nếu điểm đến của bạn là các ổ đĩa vật lý khác nhau (giữ hai bản sao vật lý của một cơ sở tệp như video nguồn cho phim kỹ thuật số).
tò mò

1
Nếu bạn đang sử dụng bash 3.0 trở lên, bạn có thể sử dụng các phạm vi như sau:cat <inputfile> | tee /path-to-files/outfile{1..4} > /dev/null
Samuel

tee < inputfile outfile1 outfile2 > /dev/nullcũng là một mẫu hữu ích như thể hiện trong câu trả lời của Taywee. Lưu ý việc sử dụng chuyển hướng io với '<' để không cần đường ống từ mèo.
Alex Telon

10

Tất cả những câu trả lời có vẻ phức tạp hơn rõ ràng:

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

thanh lịch và hoạt động, để làm điều đó cho tất cả các thư mục trong thư mục hiện tại, người ta có thể sử dụngfor d in */ ; do cp $file "$i" done
FantomX1

9

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

-btrong trường hợp có một khoảng trắng trong tên thư mục nếu không nó sẽ bị phá vỡ như một mục khác bởi xargs, có vấn đề với phiên bản echo


6

Không sử dụng cp mỗi se, nhưng ...

Điều này xuất hiện với tôi trong bối cảnh sao chép rất nhiều cảnh quay của Gopro từ thẻ SD (chậm) sang ba ổ USB (chậm). Tôi muốn đọc dữ liệu chỉ một lần, vì nó mất mãi mãi. Và tôi muốn nó đệ quy.

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

(Và bạn có thể thêm nhiều phần> () nếu bạn muốn có thêm đầu ra.)

Tôi đã không điểm chuẩn điều đó, nhưng nó chắc chắn nhanh hơn rất nhiều so với cp-in-a-loop (hoặc một loạt các lệnh gọi cp song song).


5

Để sử dụng sao chép với các xargsthư mục bằng cách sử dụng ký tự đại diện trên Mac OS, giải pháp duy nhất phù hợp với tôi với các khoảng trắng trong tên thư mục là:

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

Trong trường hợp testlà file để sao chép
./fs*/*các thư mục để sao chép để

Vấn đề là xargs xem các không gian như một đối số mới, các giải pháp để thay đổi ký tự dấu phân cách bằng cách sử dụng -dhoặc -Ekhông may làm việc không đúng cách trên Mac OS.


4

Nếu bạn muốn làm điều đó mà không có lệnh rẽ nhánh:

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


2

Về cơ bản tương đương với câu trả lời xargs, nhưng trong trường hợp bạn muốn thực thi song song:

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

Vì vậy, ví dụ, để sao chép file1 vào tất cả các thư mục con của thư mục hiện tại (bao gồm cả đệ quy):

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

Lưu ý: Điều này có lẽ chỉ chuyển tải bất kỳ mức tăng tốc đáng chú ý nào cho các trường hợp sử dụng rất cụ thể, ví dụ: nếu mỗi thư mục đích là một đĩa riêng biệt.

Nó cũng có chức năng tương tự như đối số '-P' cho xargs.


0

Không, bạn không thể.

Tôi đã tìm thấy nhiều lần tôi có thể sử dụng chức năng này vì vậy tôi đã tạo ra công cụ của riêng mình để làm điều này cho tôi.

http://github.com/ddavison/branch

khá đơn giản -
branch myfile dir1 dir2 dir3


Thường có những kịch bản mà tôi sẽ tự viết kịch bản như vậy, nhưng hiện tại tôi có xu hướng sử dụng rất nhiều máy móc khiến việc giữ tất cả chúng đồng bộ có vẻ như là một rắc rối lớn. Nếu chỉ có một cách để gắn một thư mục web đám mây /echẳng hạn, chỉ một lần trên mỗi máy, thì tôi có thể viết các công cụ truyền động của riêng mình và giữ chúng mãi mãi.
Evgeni Sergeev

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

1
Làm thế nào về một chút giải thích?
phút

Điều này thực sự có hiệu quả, nhưng một lời giải thích sẽ rất tuyệt
Ælex

0

Giả sử bạn muốn sao chép fileName.txtvào tất cả các thư mục con trong thư mục làm việc hiện tại.

  1. Nhận tất cả các tên thư mục con thông qua lsvà lưu chúng vào một số tệp tạm thời,allFolders.txt

    ls > allFolders.txt
  2. In danh sách và chuyển nó cho lệnh xargs.

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

0

Một cách khác là sử dụng mèo và tee như sau:

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

Tôi nghĩ rằng điều này sẽ khá kém hiệu quả, vì công việc sẽ được phân chia giữa một số quy trình (một cho mỗi đích) và ổ cứng sẽ ghi một số tệp cùng một lúc trên các phần khác nhau của đĩa. Tuy nhiên, nếu bạn muốn ghi một tệp ra nhiều ổ đĩa khác nhau, phương pháp này có thể sẽ khá hiệu quả (vì tất cả các bản sao có thể xảy ra đồng thời).


0

Sử dụng tập lệnh 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

Tôi đã đưa ra một downvote. Câu hỏi đặc biệt yêu cầu một giải pháp không vòng lặp.
Alex Telon

-1

Nếu bạn muốn sao chép nhiều thư mục vào nhiều thư mục, người ta có thể làm một cái gì đó như thế này:

tiếng vang dir1 dir2 dir3 | xargs -n 1 cp -r / path / toyourdir / {subir1, subir2, subir3}


-1

Nếu tất cả các thư mục đích của bạn khớp với một biểu thức đường dẫn - như chúng là tất cả các thư mục con của path/to- thì chỉ cần sử dụng findkết hợp với cpnhư thế này:

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

Đó là nó.


Tôi đã đưa ra một downvote. Câu hỏi đặc biệt yêu cầu một giải pháp không tìm thấy.
Alex Telon

Cảm ơn bạn đã rất kỹ lưỡng @AlexTelon. Tôi đoán tôi đã bỏ lỡ một chút. Tôi hy vọng bạn cũng nhất quán và bỏ phiếu cho mọi câu trả lời khác bằng cách sử dụng findtrong chuỗi.
Mig82

-2

Nếu bạn cần phải cụ thể vào các thư mục để sao chép tệp, bạn có thể kết hợp tìm với một hoặc nhiều greps. Ví dụ: để thay thế bất kỳ sự xuất hiện nào của favicon.ico trong bất kỳ thư mục con nào bạn có thể sử dụng:

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

-3

Điều này sẽ sao chép vào các thư mục con ngay lập tức, nếu bạn muốn đi sâu hơn, điều chỉnh -maxdepththam số.

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

Nếu bạn không muốn sao chép vào tất cả các thư mục, hy vọng bạn có thể lọc các thư mục mà bạn không quan tâm. Ví dụ sao chép vào tất cả các thư mục bắt đầu bằng a

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

Nếu sao chép vào một tập hợp các thư mục tùy ý / rời rạc, bạn sẽ cần đề xuất của Robert Gamble.


-3

Tôi muốn sao chép một tập tin vào nhiều thư mục như vậy: cp file1 /foo/; cp file1 /bar/; cp file1 /foo2/; cp file1 /bar2/ Và sao chép một thư mục vào các thư mục khác: cp -r dir1/ /foo/; cp -r dir1/ /bar/; cp -r dir1/ /foo2/; cp -r dir1/ /bar2/

Tôi biết nó giống như ban hành một số lệnh, nhưng nó hoạt động tốt với tôi khi tôi muốn gõ dòng 1 và bỏ đi một lúc.


7
Bạn đang trả lời một câu hỏi 6 tuổi với 15 câu trả lời khác. Câu trả lời của bạn cần phải khá mới lạ. Ý kiến ​​của tôi - nó không phải là.
Craig S. Anderson

-4

Ví dụ: nếu bạn đang ở trong thư mục mẹ của các thư mục đích bạn có thể làm:

cho tôi bằng $ (ls); làm cp nguồnfile $ i; làm xong


Câu hỏi nói rằng nó có thể với một vòng lặp for, vì vậy điều này thực sự không thêm bất cứ điều gì.
LJNielsenDk

Bị hạ bệ. Không bao giờ cố phân tích đầu rals và luôn trích dẫn các biến. for i in ./*; do cp sourcefile "$i"; done
sleblanc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.