Sao chép loại tệp cụ thể giữ cấu trúc thư mục


108

Tôi có một cấu trúc thư mục với một loạt các tệp * .csv nằm rải rác trong các thư mục. Bây giờ tôi muốn sao chép tất cả các tệp * .csv sang một đích khác giữ cấu trúc thư mục.

Nó hoạt động bằng cách làm:

cp --parents *.csv /target
cp --parents */*.csv" /target
cp --parents */*/*.csv /target
cp --parents */*/*/*.csv /target
...

và v.v., nhưng tôi muốn làm điều đó bằng một lệnh.

Câu trả lời:


126

Có bất kỳ lý do tại sao mọi người chống lại việc sử dụng find -exec? Nó rất tiện dụng.

find . -name '*.csv' -exec cp --parents \{\} /target \;

Biết công cụ của bạn. ;-)


62
Có lẽ vì điều này \ {\} \;
igo

12
'{}'cũng hoạt động tốt
OrangeDog 7/12/2015

3
Mặc dù -execdiran toàn hơn -exec, chỉ đơn giản là thay thế cái này bằng cái kia không bảo toàn cấu trúc thư mục như dự định.
Simon Shine

2
Tại sao tôi nhận được thông báo 'Bỏ qua thư mục' khi tôi cố gắng sao chép chúng bằng lệnh của bạn?
Vicky Dev

4
Bạn có thể giải thích tại sao niềng răng phải được trốn thoát ở đây?
Noumenon

46

Bạn cũng có thể sử dụng rsynccho việc này.

$ rsync -a --prune-empty-dirs --include '*/' --include '*.csv' --exclude '*' source/ target/

Nếu bạn muốn giữ các thư mục trống từ cây nguồn, hãy bỏ qua --prune-empty-dirstùy chọn:

$ rsync -a --include '*/' --include '*.csv' --exclude '*' source/ target/

Nếu bạn không muốn liên kết tượng trưng, ​​ngày sửa đổi, quyền tệp, chủ sở hữu, v.v., vui lòng thay thế -abằng một kết hợp khác -rlptgoD. ;-)


1
-mlà một phím tắt cho --prune-emty-dirs.
Geremia

Ngoài ra, -Rtùy chọn có thể được thêm vào để sao chép cấu trúc thư mục mẹ của nguồn. (xem câu trả lời của tôi ở đây.)
Geremia

-R làm việc cho tôi! Cảm ơn
gigi2

32

Bạn có thể sử dụng findcpio trong chế độ chuyển qua

find . -name '*.csv' | cpio -pdm  /target

Điều này sẽ tìm thấy tất cả các tệp .csv trong thư mục hiện tại và bên dưới và sao chép chúng vào / đích duy trì cấu trúc thư mục bắt nguồn từ ..

Nếu bạn dùng

find /path/to/files -name '*.csv' | cpio -pdm /target

nó sẽ tìm thấy tất cả các tập tin trong /path/to/filesvà bên dưới và sao chép chúng vào /target/path/to/filesvà bên dưới.


3
Tôi đã thử tất cả các câu trả lời từ trên xuống cho đến câu hỏi này và đây là câu trả lời duy nhất có hiệu quả trong lần thử đầu tiên
OscarRyz

21

Các cplệnh cho phép nhiều đối số nguồn:

cp **/*.csv --parents ../target

CAVEAT: Tôi đang sử dụng một thế giới đệ quy ở đây; đây là globstartùy chọn trong Bash 4+ và ksh, và được hỗ trợ theo mặc định trong zsh. Các quả cầu đệ quy không khớp với các tệp và thư mục ẩn và một số triển khai tuân theo các liên kết tượng trưng trong khi các tệp khác thì không .

Nếu hệ vỏ của bạn không hỗ trợ các đệ quy đệ quy hoặc nếu bạn không muốn sử dụng chúng, bạn có thể làm như sau:

  • *.csv */*.csv */*/*.csv */*/*/*.csv - điều này tất nhiên là rất dư thừa và đòi hỏi phải biết cấu trúc thư mục của bạn sâu đến mức nào.
  • $(find . -name '*.csv')- Điều này sẽ phù hợp với các tập tin và thư mục ẩn. findcũng hỗ trợ xác định xem có liên kết tượng trưng hay không, có thể hữu ích.

đây chính xác là những gì tôi đã thử (thế giới đệ quy) và nó đã tìm thấy một số nhưng không phải tất cả? khá kỳ lạ Tôi đã nhận được kết quả chính xác tương tự khi sử dụng tập lệnh copyfiles npm nhưng nếu tôi sử dụng lệnh find thì nó sẽ tìm thấy mọi thứ ...
Randyaa

@Randyaa Tôi sẽ cần thêm một số chi tiết về các tệp, chính xác, không tìm thấy để giúp bạn. Bạn có thể tìm thấy các cuộc thảo luận ở đây và tiếp tục ở đây về hành vi chính xác của toàn cầu đệ quy hữu ích.
Kyle Strand

1
Hóa ra toàn cầu đệ quy không được kích hoạt vì một số lý do ... Tôi chưa bao giờ gặp phải vấn đề này trước đây nhưng tôi đã sửa nó chỉ bằng một thực thi shopt -s globstarngay trước lệnh của tôi và tất cả đều ổn. Cảm ơn đã theo lên!
Randyaa

--parentslà những gì tôi đang tìm kiếm. cảm ơn
Josh

17

Cái này làm việc cho tôi:

find -name "*.csv" | xargs cp --parents -t /target


Câu trả lời tốt nhất với cú pháp đơn giản nhất. Hoạt động tốt và dễ nhớ. Trong nhiều trường hợp find [things] | xargs [do stuff]là rất mạnh mẽ.
Phi hành gia hàng ngày

Đã đồng ý. Rất đơn giản so với một số câu trả lời khác.
Tim B

1
Phá vỡ nếu bạn có không gian trong tên tệp
Michele Piccolini

@MichelePiccolini Spaces trong tên tệp có thể được xử lý bằng find -print0xargs -0.
pasztorpisti

8

Giả sử bạn muốn sao chép cấu trúc này từ ./sourcesang ./destination:

cd source
find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)

Tôi đã sẵn sàng để tính rằng đó là một dòng, cd sourcelà một vỏ được tích hợp sẵn.


2
Tôi không nghĩ anh ấy thực sự có nghĩa là một lệnh - chỉ cần không phải lo lắng như ví dụ của anh ấy;)

tar-Ctùy chọn để tránh phải thay đổi thư mục đầu tiên.
bart

8

Từ rsynctrang của:

-R, - có liên quan

Sử dụng các đường dẫn tương đối. Điều này có nghĩa là tên đường dẫn đầy đủ được chỉ định trên dòng lệnh được gửi đến máy chủ thay vì chỉ các phần cuối của tên tệp. Điều này đặc biệt hữu ích khi bạn muốn gửi nhiều thư mục khác nhau cùng một lúc. Ví dụ: nếu bạn đã sử dụng lệnh này:

rsync -av /foo/bar/baz.c remote:/tmp/

... điều này sẽ tạo một tệp có tên baz.c in / tmp / trên máy từ xa. Nếu thay vào đó bạn đã sử dụng

rsync -avR /foo/bar/baz.c remote:/tmp/

sau đó một tệp có tên /tmp/foo/bar/baz.c sẽ được tạo trên máy từ xa, bảo toàn đường dẫn đầy đủ của nó. Các phần tử đường dẫn bổ sung này được gọi là "thư mục ngụ ý" (tức là thư mục "foo" và "foo / bar" trong ví dụ trên).

Vì vậy, điều này cũng sẽ làm việc:

rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
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.