Lệnh cp: sao chép chính xác các thư mục tệp trong * nix

Lệnh cp: sao chép chính xác các thư mục tệp trong * nix

Bài viết này sẽ tiết lộ một số điều không rõ ràng liên quan đến việc sử dụng ký tự đại diện khi sao chép, hành vi lệnh không rõ ràng cp khi sao chép, cũng như các phương pháp cho phép bạn sao chép chính xác một số lượng lớn tệp mà không bị bỏ qua hoặc bị lỗi.

Giả sử chúng ta cần sao chép mọi thứ từ thư mục /source sang thư mục /target.

Điều đầu tiên tôi nghĩ đến là:

cp /source/* /target

Hãy sửa ngay lệnh này thành:

cp -a /source/* /target

Ключ -a sẽ thêm bản sao của tất cả các thuộc tính, quyền và thêm đệ quy. Khi không cần sao chép chính xác các quyền thì chỉ cần một khóa là đủ -r.

Sau khi sao chép, chúng ta sẽ thấy rằng không phải tất cả các tệp đều được sao chép - các tệp bắt đầu bằng dấu chấm như:

.profile
.local
.mc

và những thứ tương tự.

Tại sao điều này xảy ra?

Bởi vì các ký tự đại diện được xử lý bởi shell (bash trong trường hợp điển hình). Theo mặc định, bash sẽ bỏ qua tất cả các tệp bắt đầu bằng dấu chấm vì nó coi chúng là ẩn. Để tránh hành vi này chúng ta sẽ phải thay đổi hành vi bash sử dụng lệnh:

shopt -s dotglob

Để đảm bảo rằng thay đổi hành vi này vẫn tiếp tục sau khi khởi động lại, bạn có thể tạo tệp Wildcard.sh bằng lệnh này trong thư mục /etc/profile.d (Có lẽ bản phân phối của bạn có một thư mục khác).

Và nếu không có tệp nào trong thư mục nguồn, thì shell sẽ không thể thay thế bất cứ thứ gì thay cho dấu hoa thị và việc sao chép cũng sẽ không thành công và xảy ra lỗi. Có những lựa chọn chống lại tình huống này failglob и nullglob. Chúng ta sẽ cần thiết lập failglob, điều này sẽ ngăn lệnh được thực thi. nullglob sẽ không hoạt động vì nó chuyển đổi một chuỗi có các ký tự đại diện không tìm thấy kết quả khớp thành một chuỗi trống (độ dài bằng XNUMX), dành cho cp sẽ gây ra lỗi.

Tuy nhiên, nếu có hàng nghìn tệp trở lên trong thư mục thì nên bỏ hoàn toàn phương pháp ký tự đại diện. Sự thật là bash mở rộng các ký tự đại diện thành một dòng lệnh rất dài như:

cp -a /souce/a /source/b /source/c …… /target

Có giới hạn về độ dài của dòng lệnh mà chúng ta có thể tìm ra bằng cách sử dụng lệnh:

getconf ARG_MAX

Hãy lấy độ dài tối đa của dòng lệnh tính bằng byte:

2097152

Или:

xargs --show-limits

Chúng tôi nhận được một cái gì đó như:

….
Maximum length of command we could actually use: 2089314
….

Vì vậy, hãy làm mà không có ký tự đại diện hoàn toàn.

Hãy viết thôi

cp -a /source /target

Và ở đây chúng ta phải đối mặt với sự mơ hồ về hành vi cp. Nếu thư mục /target không tồn tại thì chúng ta sẽ nhận được thứ chúng ta cần.

Tuy nhiên, nếu thư mục đích tồn tại thì các tệp sẽ được sao chép vào thư mục /target/source.

Chúng tôi không thể luôn xóa trước thư mục /target vì nó có thể chứa các tệp chúng tôi cần và mục tiêu của chúng tôi, chẳng hạn, là bổ sung các tệp trong /target bằng các tệp từ /source.

Ví dụ: nếu thư mục nguồn và thư mục đích được đặt tên giống nhau, chúng ta đang sao chép từ /source sang /home/source, thì chúng ta có thể sử dụng lệnh:

cp -a /source /home

Và sau khi sao chép, các tệp trong /home/source sẽ được bổ sung các tệp từ /source.

Đây là một vấn đề logic: chúng ta có thể thêm tệp vào thư mục đích nếu các thư mục được đặt tên giống nhau, nhưng nếu chúng khác nhau thì thư mục nguồn sẽ được đặt bên trong đích. Làm cách nào để sao chép tệp từ/nguồn sang/đích bằng cp mà không cần ký tự đại diện?

Để khắc phục hạn chế có hại này, chúng tôi sử dụng một giải pháp không rõ ràng:

cp -a /source/. /target

Những ai quen thuộc với DOS và Linux đều đã hiểu mọi thứ: bên trong mỗi thư mục có 2 thư mục vô hình “.” và “..”, là các liên kết thư mục giả đến các thư mục hiện tại và cao hơn.

  • Khi sao chép cp kiểm tra sự tồn tại và cố gắng tạo /target/.
  • Một thư mục như vậy tồn tại và nó là /target
  • Các tệp từ/nguồn được sao chép vào/đích một cách chính xác.

Vì vậy, hãy treo nó trong khung in đậm để tưởng nhớ hoặc trên tường:

cp -a /source/. /target

Hành vi của lệnh này là rõ ràng. Mọi thứ sẽ hoạt động mà không có lỗi, bất kể bạn có một triệu tệp hay không có tệp nào.

Những phát hiện

Nếu bạn cần sao chép tất cả các tập tin từ thư mục này sang thư mục khác, chúng tôi không sử dụng ký tự đại diện, thay vào đó nên sử dụng chúng cp kết hợp với dấu chấm ở cuối thư mục nguồn. Thao tác này sẽ sao chép tất cả các tệp, kể cả các tệp bị ẩn và sẽ không bị lỗi với hàng triệu tệp hoặc không có tệp nào cả.

bạt

vmspike đề xuất một phiên bản lệnh có kết quả tương tự:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

LƯU Ý: viết hoa chữ cái T có ý nghĩa. Nếu bạn trộn nó lên, bạn sẽ nhận được một thứ hoàn toàn rác rưởi: hướng sao chép sẽ thay đổi.
Cảm ơn:

  • Các công ty RUVDS.COM để được hỗ trợ và có cơ hội xuất bản trên blog của bạn trên Habré.
  • Mỗi hình ảnh Khái niệm ba. Hình ảnh rất lớn và chi tiết, có thể mở trong một cửa sổ riêng.

PS Vui lòng gửi bất kỳ lỗi nào bạn nhận thấy trong một tin nhắn riêng tư. Tôi tăng nghiệp của mình cho việc này.

Lệnh cp: sao chép chính xác các thư mục tệp trong * nix

Nguồn: www.habr.com

Thêm một lời nhận xét