Linux: Sao chép tất cả các tệp khớp mẫu từ thư mục và thư mục con vào một thư mục duy nhất


31

Nếu tôi muốn sao chép tất cả các *.sotập tin từ srcđể dsttôi muốn làm:

cp src/*.so dst

Tuy nhiên, tôi muốn sao chép tất cả *.socác tệp từ src và nó sẽ chuyển sang dst. Bất kì manh mối nào?

Câu trả lời:


36

Thử:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

17
findcó thể thực hiện khớp mẫu và thực hiện các lệnh. Không cần phải đầu ra đầu ra của nó:find src/ -type f -name '*.so' -exec cp '{}' dst/ ';'
jáquer

1
Vâng, tuy nhiên, việc đọc một đường ống thường dễ dàng hơn, cũng là khả năng khớp mẫu grepvượt xa các mẫu vỏ đơn giản được sử dụng trong -nametham số find. xargscũng mạnh hơn nhiều so với -exectham số find.
Mike Insch

2
Giải pháp của @jaquer tốt hơn nhiều vì trên tiện ích MacOSX xargs không có tùy chọn -i. Nhưng giải pháp của ông hoạt động như một lá bùa.
bialix

Tôi đã vật lộn với một thông báo lỗi về đối số -i cho xargs cho đến khi tôi đọc nhận xét từ @bialix về giải pháp của jaquer, hoạt động hoàn hảo trên máy Mac của tôi. Cảm ơn
svannoy

Điều này sẽ tạo ra các thư mục con khi cần thiết?
Lennart Rolland

15

Nếu bạn đang sử dụng Bash, bạn có thể bật globstar tùy chọn shell để khớp các tệp và thư mục theo cách đệ quy:

shopt -s globstar
cp src/**/*.so dst

Nếu bạn cần tìm các tệp có tên bắt đầu .và / hoặc các tệp trong và dưới các thư mục có tên bắt đầu ., hãy đặt dotglobtùy chọn cũng (ví dụ: với shopt -s dotglob). Bạn có thể đặt cả hai trong một lệnh:

shopt -s globstar dotglob

Không sao chép tệp trong thư mục con bắt đầu bằng a. trong tên của họ
rboy

8

Tôi đã thử lệnh được đề xuất bởi Mike:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

nhưng nó đã kết thúc với việc bỏ tất cả các tệp vào thư mục dstvới các đường dẫn tương đối bị mất.

Để giữ các đường dẫn tương đối, lệnh cần được sửa đổi thành:

find src/ -type f | grep -i so$ | xargs -i cp {} dst/{}

7
+1. Tuy nhiên, điều này giả định rằng các thư mục tương ứng với các đường dẫn nguồn tương đối tồn tại bên dưới dst. Trong trường hợp không phải vậy, sử dụng cp --parents. Ngoài ra, hãy chắc chắn để trích dẫn tên tập tin. Do đó: ... | xargs -i cp --parents "{}" dst(lưu ý rằng đối số cuối cùng cpbây giờ là "chỉ" thư mục đích). Lệnh có thể được thực hiện thậm chí ngắn hơn (và có thể nhanh hơn) bằng cách sử dụng -tcờ : ... | xargs cp --parents -t dst.
Stephan202

1
@ Stephan202 Tôi phải sử dụng... | xargs cp {} --parents -t dst.
warvariuc

đối với những người trên mac, --parentskhông có sẵn. Tôi đã sử dụng dittoở vị trí của nó: stackoverflow.com/questions/11246070/cp-parents-option-on-mac
Bryan Young

3

Một cách khác để làm điều này là như thế này:

find src/ -type f -name "*.so" -exec cp {} dst/ \;

Và điều này sẽ làm giảm số lượng cpquá trình : ... -exec cp -t dst/ {} +.
Kamil Maciorowski

Này Kamil! Cảm ơn bạn đã bình luận! Bạn có thể vui lòng giải thích cho tôi làm thế nào giải pháp của bạn làm cho mọi thứ nhanh hơn! Luôn sẵn sàng tìm hiểu thêm :)
Kyriakos

Khi bạn kết thúc -execvới ;, {}được thay thế bằng một con đường tại một thời điểm. Bạn nhận được một riêng cpcho mỗi tập tin. Với +cú pháp findthay thế {}bằng nhiều kết quả (tối đa giới hạn do hệ thống xác định theo chiều dài của dòng lệnh; hạn chế: {}phải là điều cuối cùng trước +đó, do đó cp -t). Tạo và chấm dứt một quá trình là điều tương đối tốn kém. Vì lý do này, nó tốt để sử dụng +bất cứ khi nào bạn mong đợi nhiều kết quả. Trong trường hợp này, việc sao chép rất nhiều tệp có thể mất rất nhiều thời gian vì vậy sự khác biệt có thể vượt qua mà không được chú ý; tuy nhiên đó là một thực hành tốt.
Kamil Maciorowski

1

Grep có thể được thay thế bằng cách sử dụng tên của find :

find src/ -type f -name "*.so" | xargs -i cp {} dst/{}
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.