Tại sao mkdir không có cờ -p được đặt theo mặc định để cho phép tạo thư mục lồng nhau?


11

Tôi thấy không có lý do tại sao -pcờ trên mkdirkhông nên được đặt theo mặc định.

  -p, --parents     no error if existing, make parent directories as needed

Đó là một lệnh không phá hủy từ những gì tôi có thể thấy. Tôi đã bỏ lỡ một cái gì đó quan trọng về cách làm việc này?

Thứ hai là có một cách dễ dàng để biến điều này thành hành vi mặc định của mkdir?


2
đặt cái này trong .bashrc : alias mkdir="mkdir -p".
Kevin

Sau tất cả các cuộc thảo luận, tôi đã quyết định đi theo một bí danhmkdp
Treffynnon

Câu trả lời:


6

Đây là một tính năng tùy chọn, không phải lúc nào cũng mong muốn - đặc biệt là trong các tập lệnh. Xem xét các nhược điểm sau trong trường hợp kịch bản:

  • Thực tế là thư mục đã tồn tại không được báo cáo: Nếu một tập lệnh được cho là đặt một số tệp trong một thư mục mới được tạo và thư mục đó đã tồn tại và chứa các tệp, tập lệnh có thể gây ra nhiều lộn xộn. (Sẽ rất khó để sau đó lọc ra các tệp được đặt ở đó bởi tập lệnh.)
  • Mặt trái của phần trên, một số tập lệnh (hoặc một phần của phần đó) có thể phụ thuộc vào cấu trúc thư mục được tạo trước đó (có thể bởi gói / tập lệnh khác). Ví dụ, tập lệnh cài đặt gói có thể cần đặt các thư viện trong một thư mục con /usr/local/lib/GreatSoftware/ImportantPartOfIt, nhưng các thư viện phụ thuộc vào / liên kết đến nội dung bên dưới /usr/local/lib/GreatSoftware. Nếu điều này bị thiếu, kịch bản không nên tiếp tục.

Hành vi chung mkdirlàm cho nó dễ dàng và tự nhiên, vì những tình huống như vậy được báo cáo và có thể được bắt gặp ngay lập tức.


Bạn có thể tạo bí danh cho nó nếu bạn muốn luôn sử dụng mkdir -ptrong trình bao của mình:

alias mkdir='mkdir -p'

(Điều này sẽ đi đến .bashrchoặc bất kỳ cấu hình nào mà shell của bạn sử dụng.)


1
Tôi sẽ không đề xuất với bí danh một lệnh tiêu chuẩn để làm cho nó hoạt động theo cách không chuẩn. Điều đó sẽ làm cho các kịch bản không di động và có thể gây nhầm lẫn cho độc giả. Tạo một bí danh hoặc chức năng mới, như alias mkdp="mkdir -p"sẽ được khuyến khích hơn.
jlliagre

2
@jlliagre Không, nó sẽ không ảnh hưởng đến các tập lệnh. Các bí danh được xác định cục bộ trong .bashrckhông (thông thường) ảnh hưởng đến môi trường của chúng.
rozcietrzewiacz

Thật vậy nhưng bạn đã bỏ lỡ quan điểm của tôi. Bí danh một lệnh tiêu chuẩn để thay đổi hành vi của nó, ngay cả đối với việc sử dụng của riêng bạn, không phải là một cách làm được khuyến nghị. Ví dụ tồi tệ nhất là phổ biến alias rm='rm -i'.
jlliagre

1
@jlliagre Không được đề xuất bởi ai? ;) Nhưng vâng, tôi đồng ý, bản thân tôi sẽ sử dụng một bí danh khác - nhưng vì lý do thực tế, không phải ý thức hệ. Tôi cũng không nghĩ rm -ibí danh luôn xấu - mặc dù có thể dẫn đến những thói quen xấu. Chắc chắn không phải tất cả các bí danh lệnh đều tốt / xấu như nhau - xem xét ls="ls --color=auto"hoặc ssh="TERM=xterm ssh"ví dụ.
rozcietrzewiacz

Không có gì ý thức hệ trong đề nghị của tôi. Bí danh rm chịu trách nhiệm gián tiếp cho nhiều tập tin bị mất (tôi đã gặp rất nhiều nạn nhân của bí danh này). Tôi đã nghi ngờ mkdir có một tác dụng phụ không mong muốn ở mức độ thấp hơn nhiều. Tất nhiên, tôi không chống lại mỹ phẩm, không hành vi, thay đổi như ví dụ ssh và ls của bạn.
jlliagre

16

Tất nhiên người ta có thể lập luận rằng việc tạo thư mục mẹ nên là mặc định và một số tùy chọn kiểm tra có thể được sử dụng để ngăn chặn việc tạo thư mục nếu cha mẹ không tồn tại.

Nhưng lý do tại sao nó là cách khác xung quanh chỉ là lịch sử. Phiên bản cơ bản của mkdir không tạo thư mục gốc. Đây là lý do tại sao các bản phân phối X11 đi kèm với một lệnh có tên mkdirhier có thể hoàn thành nhiệm vụ này: kiểm tra xem các thư mục mẹ có tồn tại không và tạo chúng nếu cần thiết.

Sau đó, chức năng này đã được thêm vào lệnh mkdir trên nhiều phiên bản UNIX (hiện tại tôi không biết nó có trong tiêu chuẩn POSIX không). Để duy trì khả năng tương thích, tính năng này đã được cung cấp bằng cách bật cờ tùy chọn : -p.

Tại sao nó được bật theo mặc định? Các tập lệnh có thể dựa vào mkdir không thành công nếu thư mục cha không tồn tại. Đặc biệt là người dùng root , việc tạo các cây thư mục theo mặc định có thể nguy hiểm.

Thí dụ:

 if mkdir /backup/$(uname -n)/$(date +%Y%m%d)
  then
    perform_backup ...

Trong ví dụ này, thư mục sẽ được tạo và sao lưu được thực hiện ngay cả khi hệ thống tập tin /backupkhông được gắn kết và cha mẹ /backup/$(uname -n)không tồn tại nếu mặc định sẽ là cách khác.

Nguyên tắc nhỏ: Không nên thay đổi hành vi mặc định của bất kỳ công cụ nào. Nếu muốn cung cấp tùy chọn để cho phép thay đổi hành vi mặc định.


2
Tôi thích ví dụ gắn kết bạn đã sử dụng ở đây. Tôi đã không nghĩ về kịch bản cụ thể đó.
Treffynnon

1
Các tùy chọn -p (và -m) được System V giới thiệu vào năm 1983. Cả hai đều chắc chắn là một phần của tiêu chuẩn POSIX.
jlliagre

4

Tôi nghĩ rằng, đây là triết lý. Lệnh mkdir (1) trần (không có tùy chọn) đại diện cho lệnh gọi hệ thống mkdir (2) , cung cấp chức năng của nó trong shell, không làm gì nhiều hơn hoặc ít hơn.


4

Ban đầu , chỉ có mkdirlệnh trần . Theo nguyên tắc thiết kế của Unix, lệnh đơn giản này đã thực hiện một nhiệm vụ đơn giản: tạo thư mục.

Sau đó, mkdircó được một -ptùy chọn để xử lý một trường hợp sử dụng phổ biến trong đó người gọi muốn tạo 0, một hoặc nhiều thư mục để đảm bảo rằng một đường dẫn cụ thể tồn tại. Điều này đã không được thực hiện các hoạt động mặc định vì một số lý do. Đầu tiên, không phải tất cả các hệ thống đều có tính năng phức tạp hơn này và yêu cầu -ptùy chọn có nghĩa là các tập lệnh đã sử dụng nó sẽ nhận được thông báo lỗi hợp lý (đại loại như vậy mkdir: invalid option -z) thay vì thỉnh thoảng không tạo được thư mục. Thứ hai, và quan trọng nhất, hành vi của mkdir -pkhông phải là sự thay thế tương thích mkdirtrong mọi trường hợp.

Đặc biệt, trên hầu hết các hệ thống tập tin, mkdirlà một hoạt động nguyên tử . Nếu một chương trình chạy mkdir playgroundvà lệnh thành công, chương trình biết rằng nó đã tạo playgroundthư mục. Điều này cho phép chương trình coi thư mục mới là sân chơi độc quyền của nó: nếu một phiên bản khác của cùng một chương trình đang chạy đồng thời, lệnh gọi của nó mkdir playgroundsẽ thất bại. Thuộc tính này rõ ràng không được cung cấp bởi mkdir -pvì nó cho phép đối số tồn tại.

Nếu mkdir -pđã tồn tại từ đầu, nó có thể đã được tạo ở chế độ mặc định, giống như mkdir -avới lệnh tạo thư mục đơn. Nhưng điều đó sẽ không tuân theo triết lý thiết kế Unix thông thường: hầu hết các tiện ích cơ bản là các trình bao bọc đơn giản xung quanh các nguyên thủy cơ bản, với hành vi fancier (như tạo nhiều thư mục trong một lần) yêu cầu các tùy chọn ưa thích.


2

Đối với tôi, vấn đề là hành vi của tùy chọn -p nếu nó là mặc định về cơ bản là một tác dụng phụ. Nó thêm sự phức tạp cho một lệnh bằng cách làm một cái gì đó bổ sung cho những gì bạn yêu cầu nó làm. Đó là một điều vô hình cần phải nhớ. Một trong những quy tắc cơ bản của thực hành lập trình âm thanh là tránh tác dụng phụ.

Các ngôn ngữ lập trình hiện đại mạnh đến mức dễ dàng xây dựng bất kỳ lệnh phức tạp nào bạn có thể cần từ các nguyên thủy mà ngôn ngữ cung cấp. Làm như vậy liên quan đến việc đưa ra quyết định có ý thức về những hành vi được yêu cầu và cũng để lại một bản ghi cụ thể, rõ ràng về những gì đã được thực hiệ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.