Tại sao chương trình unix mv không cần tùy chọn -R (đệ quy) cho các thư mục nhưng cp không cần nó?


58

Tôi luôn bị rối khi cần sử dụng cphoặc mv: "tôi có cần -Rtùy chọn khi làm việc với dir không?" Trong GNU coreutils cpcó cần -Rmvkhông.

Tôi chỉ không thể tìm thấy bất kỳ lý do tại sao cpcần -Rtùy chọn để sao chép các thư mục và mvkhông. Tôi nghĩ rằng cping dir mà không có -R(nhưng hành xử đệ quy như có -Rvà giống như mvvậy) sẽ không gây ra bất kỳ vấn đề nào ngoại trừ phá vỡ thói quen của ai đó khi sử dụng công cụ.

Bạn có biết lời giải thích nào không? Có thể nó có một lý do từ lâu?


Câu hỏi bổ sung: tại sao các nhà phát triển coreutils không tạo các cpthư mục sao chép theo mặc định?

Câu trả lời:


45

Một thư mục (về mặt khái niệm) là một "tệp" đặc biệt chứa danh sách các tên và số inode mà các tên đó trỏ đến. Một số tên có thể là thư mục con. Có một mục đặc biệt ..trỏ đến thư mục cha.

Vì vậy, rõ ràng, thay đổi tên của một tập tin rất dễ dàng: bạn chỉ cần thay đổi tên trong mục nhập thư mục, không có gì khác. Điều này cho biết tập tin thực sự là một tập tin hay là một "tập tin" được sử dụng để lưu trữ nội dung của thư mục khác. Thật vậy, cùng một tòa nhà renamechọc trời làm cả hai.

Sao chép, tuy nhiên, là một hoạt động tầm thường ít hơn nhiều. Bạn chỉ có thể sao chép thư mục "tệp", nhưng sau đó bạn có hai thư mục chứa các tệp giống nhau (chúng sẽ là liên kết cứng). Nếu bạn có một hệ thống cho phép các liên kết cứng vào các thư mục, thì chúng sẽ như vậy, nhưng vì không có hệ thống hiện đại nào cho phép, ít nhất là không root, bạn phải thực hiện bản sao đó cho mỗi thư mục con. Bạn thực sự có thể yêu cầu cphành vi này với cp -lR: -lcho liên kết cứng, -Rcho đệ quy đó.

Nhưng để lại mọi thứ liên kết có thể không phải là những gì bạn muốn. Thay vào đó, bạn muốn cpsao chép từng tập tin. Đó là một hoạt động khá tốn kém: mỗi tệp phải được đọc vào bộ nhớ và được ghi lại ra đĩa ở vị trí thứ hai. Nó thực sự cần một số tòa nhà, để mở, đọc, viết và đóng các tệp, và điều đó phải được lặp lại cho mỗi tệp.

Các hệ thống tập tin truyền thống cũng hoạt động theo cách này trên đĩa. Không có cách nào để sao chép một loạt các tệp, ngoài việc đi qua từng tệp riêng lẻ và sao chép nó, và đó là các loại hệ thống tệp được sử dụng khi các tiện ích dòng lệnh cơ bản được thiết kế.


được mving từ một hệ thống tập tin khác nhau "chỉ cần thay đổi tên trong mục nhập thư mục"?
rslnx

5
Không, hệ thống tập tin chéo giống như một bản sao + xóa (thực sự, tòa nhà renamesẽ thất bại đối với hệ thống tập tin chéo). Không chắc chắn nếu, trong lịch sử, mvthậm chí hỗ trợ di chuyển chéo fs.
derobert

9
Tôi có thể nói với bạn, từ kinh nghiệm trực tiếp không suy đoán, rằng cổ điển mvkhông hỗ trợ di chuyển thiết bị chéo. Nó thường chỉ thử một rename()và in một thông báo lỗi nếu thất bại. Tôi vẫn còn nhớ cảm giác sốc khi lần đầu tiên tôi vô tình sử dụng tính năng mới. Tại sao mv này mất nhiều thời gian? Ồ, đó là một bản sao đệ quy mà tôi không có ý định!
Alan Curry

5
@RuslanKhusnullin Tùy chọn dòng lệnh cho các lệnh phổ biến rất khó thay đổi, do sử dụng chúng trong các tập lệnh shell. Ai đó có thể phụ thuộc vào hành vi từ chối sao chép hiện tại của cp. Các công cụ cross-fs có lẽ được đánh giá là ít có khả năng gây ra vỡ, mặc dù như bạn có thể thấy, nó vẫn khiến Alan ngạc nhiên.
derobert

1
@derobert, nó không (hệ thống tập tin chéo mvchỉ hoạt động cho các tệp riêng lẻ trên BSD 4.2 trên VAX).
vonbrand

21

Hãy để tôi bắt đầu bằng cách hỏi một câu hỏi khác:

Sự khác biệt giữa cpvà là cp -Rgì?

Chà, không có -Rcờ, chỉ có thể sao chép các tệp, vì điều bất thường là ai đó muốn sao chép một cách không đệ quy một thư mục: Một bản sao không đệ quy sẽ chỉ dẫn đến một tên thứ hai cho thư mục, chỉ vào cùng một thư mục kết cấu. Bởi vì đó hiếm khi là những gì mọi người muốn, và thực sự có một chương trình riêng biệt thực hiện điều này ( ln), một bản sao thư mục không đệ quy không được phép.

Điều gì sau đó có thể là sự khác biệt giữa mvmv -R?

mv a bchỉ đổi tên một mục trong thư mục, vì vậy nếu một thư mục là mved, nội dung của nó cũng tự động được di chuyển. Theo nghĩa đó, mvđã cung cấp thuộc tính đệ quy, tức là "đổi tên" của tất cả các mục trong thư mục được đổi tên, ví dụ từ từ a/1sang b/1. Một mvđiều đó không làm điều đó, tức là trong đó đổi tên một thư mục ađể b, nhưng giữ a/1như a/1, không phải là những gì mọi người hiểu khi họ đề cập đến di chuyển một cái gì đó: Khi bạn di chuyển một cái tủ, các nội dung của tủ được chuyển là tốt. Hoạt động khác đó, di chuyển một thư mục không có nội dung của nó, cũng đã có sẵn, nó được gọi mkdir.


2
Điều đó đúng, tôi chỉ nghĩ cpmvnhư các hoạt động mà chúng được đặt tên: 'tạo một bản sao' và 'di chuyển'. Vì vậy, nếu tôi muốn tạo một bản sao của một tách cà phê, tôi sẽ mong đợi có một tách cà phê khác có cùng chất làm đầy (cà phê uống). Vấn đề là các công cụ này không dành cho 'người bình thường' mà dành cho những người mới biết về cấu trúc hệ thống tệp và đĩa, chứ không phải các thực thể ảo như tệp và thư mục của tệp.
rslnx

1
Cấu trúc tốt, phản ứng lý luận.
Spedge

1
@RuslanKhusnullin tương tự cà phê của bạn làm việc cho cpmvquá - nó không đòi hỏi bất kỳ mức độ "nerdness" để hiểu, chỉ cảm giác chung cơ bản. Một bản sao thực sự của một tách cà phê không phải là một tách rỗng - bạn phải sao chép đệ quy không chỉ tách mà cả tất cả nội dung của nó (cà phê). Tuy nhiên, khi bạn di chuyển một tách cà phê, bạn không phải di chuyển các nội dung riêng biệt - nội dung di chuyển với hộp đựng một cách tự nhiên.
jw013

1
@ jw013 Bạn đã gây ấn tượng với tôi "khi bạn di chuyển một tách cà phê bạn không phải di chuyển nội dung riêng biệt", điều đó thực sự có ý nghĩa, cảm ơn bạn. Nhưng đó là một lớp trừu tượng khác. Tôi nghĩ bạn có nghĩa là "coi một tệp là một nút" trong khi tôi nghĩ các tệp như các chuỗi byte không có thông tin meta.
rslnx

6

Thông thường khi tôi gặp rắc rối với logic Unix, tôi nhìn vào Plan9 để xem cách các nhà phát minh Unix thực hiện các nhiệm vụ tương tự nhiều năm sau đó mà không bị kẹt trong khả năng tương thích ngược.

Vì vậy, Plan9 cung cấp cpmvcác công cụ để chỉ hoạt động với các tệp.

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

Để sao chép một thư mục đó dircpthực sự là @{cd fromdir && tar c .} | @{cd todir && tar xT}(cú pháp vỏ RC)

Để di chuyển một dir tôi nghĩ rằng chỉ có dircp d1 d2 && rm -r d1

Tôi nghĩ rằng quyết định này chỉ giới hạn cpvà chỉ mvcho các hoạt động tệp (không phải thư mục) mang lại sự rõ ràng hơn cho các hoạt động của đĩa và sử dụng tarđể sao chép cây tệp rất thoải mái để hiểu và viết kịch bản.

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.