Làm cách nào để sao chép các tập tin và thư mục con ẩn (bắt đầu bằng dấu chấm) trong linux?


10

Làm cách nào để sao chép các tệp ẩn và thư mục con ẩn (những tệp bắt đầu bằng dấu chấm) trong thư mục A sang thư mục B? Ví dụ: nếu tôi có cấu trúc này:

A/a
A/b
A/.a
A/.b/
A/.b/somefile
A/.b/.c

Tôi muốn sao chép vào B chỉ các tệp ẩn và thư mục con ẩn trong A:

B/.a
B/.b/
B/.b/somefile
B/.b/.c

Tôi đã thử lệnh này: cp A/.* Btừ câu hỏi siêu người dùng khác này . Tuy nhiên, nó không sao chép các thư mục con. Cũng đã thử cp -r A/.* B, nhưng nó sao chép .để tôi kết thúc bằng một bản sao chính xác của A (bao gồm các tệp thông thường). Bất kỳ trợ giúp được đánh giá cao.

Câu trả lời:


16

Miễn là bạn chỉ tìm kiếm các tệp và thư mục ẩn ở cấp độ A và không muốn, chẳng hạn

A/b/.hidden

để được sao chép, bạn sẽ có thể sử dụng điều này:

cp -r A/.[^.]* B

Về cơ bản, nó có nghĩa là sao chép bất cứ thứ gì bắt đầu bằng một .và sau đó bất kỳ ký tự nào ngoài .Bộ lọc đó ra ...

Chỉnh sửa: Đã xóa -p khỏi lệnh cp vì Asker không cho biết anh ta muốn giữ bất kỳ quyền sở hữu, ngày tháng, v.v.


Này làm việc cho các ví dụ tập tin và thư mục tên được đưa ra trong câu hỏi, nhưng nội dung của câu hỏi nói “các tập tin ẩn và thư mục con ẩn (những người bắt đầu với một dấu chấm)”, và câu trả lời này sẽ không tìm thấy tập tin và thư mục có tên bắt đầu với hai dấu chấm; ví dụ ..c.
Scott

Đó là một trường hợp khá, nhưng một mối quan tâm chính đáng không hơn không kém. Tôi đã không cân nhắc điều đó. Bạn có thể giải thích điều đó bằng cách chuyển sang .*[^.]nhưng sau đó bạn sẽ bỏ lỡ các tệp kết thúc bằng a .. Tôi nghĩ rằng bạn thực sự sẽ cần mở rộng toàn cầu để thực sự giải thích cho tất cả các trường hợp.
Toàn năng

4

Vấn đề với A/.*là có thư mục .trong Ađó cũng phù hợp với mô hình.

Bạn có thể bật các mẫu toàn cầu mở rộng và sử dụng như sau:

shopt -s extglob
cp -r A/.!(?(.)) B    

Nó khớp với các tệp có tên bắt đầu bằng dấu chấm và ký tự thứ hai không phải là dấu chấm cũng không có gì (? (.) Không khớp với dấu chấm hoặc dấu chấm ,! (...) phủ định nó, tức là! (? (.)) hơn không có gì hoặc một dấu chấm).


+1 cho câu trả lời đúng. Lưu ý rằng .!(@(|.))(AFAICT) tương đương với ở trên, (IMNSHO) rõ ràng hơn một chút và chỉ dài hơn một ký tự.
Scott

3

Đối với những trường hợp như thế này sẽ khuyên bạn nên sử dụng findthay vì cpnhư thế này:

find A/ -type f -maxdepth 1 -name '.*' -exec cp -p {} B/ \;

Cú pháp cơ bản bị phá vỡ như thế này:

  • find A/ -type f: findcác mục trong thư mục A/có loại là tệp (thay vì thư mục)
  • -maxdepth 1 -name '.*': Để điều này cho một maxdepthtrong 1 thư mục và namebắt đầu với ..
  • -exec cp -p {} B/ \;: Và một khi những tập tin được tìm thấy, execcác cplệnh với một -plá cờ để giữ gìn ngày / lần từ nguồn ( {}) đến đích của B/.

Tôi thích sử dụng maxdepthđể thêm một lớp điều khiển để không vô tình sao chép toàn bộ hệ thống tập tin. Nhưng hãy thoải mái loại bỏ điều đó.


0
 for item in `find A -type d | grep -E "\."` ; do cp -r $item B ; done
  • find A -type d cung cấp một danh sách đệ quy trong A chỉ với các thư mục
  • grep -E "\." lọc các thư mục có dấu chấm (tức là: các thư mục ẩn)
  • tùy chọn -E là cần thiết ở đây vì không có nó có nghĩa là "thư mục hiện tại"
  • dấu gạch chéo ngược là để tránh ý nghĩa của "bất kỳ ký tự" nào
  • cp -r sao chép đệ quy

Tôi đã tạo cấu trúc tệp và thư mục cho A và thực thi lệnh trong Git Bash (hiện tại tôi không có linux) và nó đã hoạt động.


Điều này phá vỡ nếu các tệp có khoảng trắng hoặc ký tự đặc biệt trong tên hoặc đường dẫn của chúng.
slhck

Cảm ơn bạn đã chú ý :) Thật ra tôi đã giới hạn trong "trường hợp thử nghiệm" của @gaboroncancio. Nếu bạn có thể đưa cho tôi pin thử nghiệm khác, tôi có thể cố gắng cải thiện điều đó (tất nhiên nếu bạn muốn, hãy tự cải thiện nó để chỉnh sửa phản hồi này hoặc tạo câu trả lời mới)
malarres

Bạn có thể chỉ cần đặt các dotfiles vào một thư mục được gọi A B, và sau đó nó sẽ hành động bất ngờ vì nó sẽ mở rộng sang cp -r A B/.dotfile B. Lời khuyên chung là không nên phân tích cú pháp findhoặc lsđầu ra . Nếu bạn sử dụng, findbạn cũng nên sử dụng các tùy chọn riêng của mình để lọc chứ không phải grep, và nếu bạn đặt findđầu ra ở một nơi khác, hãy sử dụng -print0hoặc gọi trực tiếp lệnh bạn muốn. Xem find hướng dẫn .
slhck

Thậm chí, nói chung, khi làm việc với các tệp, an toàn nhất là sử dụng các khối vỏ như được giải thích trong các câu trả lời khác (mặc dù chúng thường được yêu cầu extglobđặt).
slhck

Cảm ơn các liên kết. Hãy để lại findphân tích cú pháp sau đó.
malarres

0

Để thay thế, bạn có thể sử dụng lệnh khác này nếu ký tự thứ hai là chữ và số ( nguồn ):

cp -r A/.[a-zA-Z0-9]* B

Này làm việc cho các ví dụ tập tin và thư mục tên được đưa ra trong câu hỏi, nhưng nội dung của câu hỏi nói “các tập tin ẩn và thư mục con ẩn (những người bắt đầu với một dấu chấm)”, và câu trả lời này sẽ không tìm thấy tập tin và thư mục có tên bắt đầu với một dấu chấm và một ký tự đặc biệt; ví dụ, .@foohoặc ..c.
Scott

Đó là lý do tại sao tôi chỉ ra rằng nó hoạt động nếu ký tự thứ hai là chữ và số. ;)
gaboroncancio
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.