Có 'rm. *' Bao giờ xóa thư mục mẹ?


53

Biểu thức .*được mở rộng bằng bash để bao gồm các thư mục hiện tại và thư mục mẹ:

$ ls -la
total 2600
drwxrwxrwx   2 terdon terdon 2162688 Sep 10 16:22 .
drwxr-xr-x 142 terdon terdon  491520 Sep 10 15:34 ..
-rw-r--r--   1 terdon terdon       0 Sep 10 16:22 foo
$ echo .*
. ..

Nếu tôi chạy rm -rf .*trên Debian của mình bằng GNU bash version 4.2.36(1)-releasermtừ đó rm (GNU coreutils) 8.13, tôi nhận được thông báo này:

$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'

Đây có phải là một điều GNU hay nó là POSIX? Có bất kỳ hệ thống * nix nào mà lệnh trên sẽ âm thầm xóa ...không?

Ngoài ra, đây là một tính năng an toàn của shell hay của rmchính lệnh?


4
Tôi biết câu hỏi này là trong bối cảnh rm, nhưng tôi nghĩ rằng nó là đáng nói rằng bạn vẫn có thể có kết quả bất ngờ với chmod, chown, vv khi kết hợp .*.
Aaron Copley

Câu trả lời:


59

Phiên bản mới nhất (kể từ năm 2017) của thông số POSIX cho rmtiện ích có tại đây (và phiên bản trước đó ở đó ) và cấm xóa ....

Nếu một trong hai dấu chấm hoặc dấu chấm chấm được chỉ định là phần tên cơ sở của toán hạng (nghĩa là thành phần tên đường dẫn cuối cùng) hoặc nếu toán hạng giải quyết vào thư mục gốc, rm sẽ viết thông báo chẩn đoán thành lỗi tiêu chuẩn và không làm gì cả nhiều hơn với các toán hạng như vậy.

Theo ghi nhận của @jlliagre, phần về /là một bổ sung trong SUSv4.

Thông số Unix có sẵn công khai lâu đời nhất mà tôi có thể tìm thấy ( XPF4 CAE rev2 (1994)), đã chỉ định rằng ...không thể xóa được, mặc dù các nhận xét trong tệp thay đổi tệp GNU cho thấy nó đã là trường hợp trong thông số POSIX cũ hơn.

Lưu ý rằng nó áp dụng cho dir/..../là tốt, nhưng một số triển khai (kể cả UNIX chứng nhận như Solaris 11 và MacOS) vẫn không bảo vệ chống lại rm -rf ../hoặc rm -rf .*/).

lịch sử

Đoàn kết sớm

Các -rtùy chọn để rmđược bổ sung trong Unix V3 (1973) mặc dù nó chỉ xóa nội dung của các thư mục, bạn vẫn sẽ cần phải sử dụng rmdirđể loại bỏ các thư mục.

Điều đó đã thay đổi trong Unix V7 (1979, bản phát hành cũng giới thiệu shell Bourne và từ đó hầu hết các Unices đều xuất phát). rm -rbây giờ cũng loại bỏ các thư mục và sẽ không xóa ..cây thư mục. Các trang người đàn ông bang:

Cấm xóa tệp ..chỉ để tránh hậu quả chống xã hội do vô tình làm điều gì đó như thế nào rm -r .*.

(mặc dù người ta có thể lập luận rằng rm -r .*vẫn chống đối xã hội vì nó xóa mọi thứ vì .được bao gồm).

Nó vẫn chấp nhận xóa .mặc dù nó sẽ không hủy liên kết .hoặc ..các mục. Vì vậy, sau đó, rm -r .là một cách hiệu quả để làm trống thư mục hiện tại.

Cũng lưu ý rằng các biện pháp bảo vệ chỉ dành cho một ..cuộc tranh luận theo nghĩa đen , không phải cho dir/..hoặc ./... Vì vậy, rm -rf ./.*vẫn sẽ loại bỏ mọi thứ trong thư mục cha theo cách đệ quy.

Thật thú vị khi thấy rằng điều đó đã khắc phục được lỗi / lỗi không phù hợp bằng cách mà các khối có thể bao gồm ...trong bản mở rộng của chúng. Điều đó đã được cố định trong trình bao Forsyth (cơ sở cho trình bao Minix gốc và pdksh) vào cuối những năm 80, zsh(1990) và fish(2005) nhưng không phải là các trình bao khác và đặc biệt không phải là shngôn ngữ POSIX yêu cầu mở rộng .*để bao gồm ...nếu chúng được trả về bởi readdir()( bashgiải quyết vấn đề một phần chỉ với shopt -s dotglobnơi mà các khối u (trừ .xxxnhững vấn đề) không bao gồm .hoặc .., và với ksh, bạn có thể khắc phục bằng cách thực hiện FIGNORE='@(.|..)').

Khi chính xác việc cấm .cũng được thêm vào không phải lúc nào cũng rõ ràng và thay đổi theo từng Unix. Một vài phát hiện dưới đây.

BSD

Việc cấm .được thêm vào khoảng giữa 2.9BSD (1983) và 2.10BSD (1987) và giữa 4.2BSD (1983) và 4.3BSD (1986) (xem thay đổi này được đánh dấu thời gian 1985 trong unix-history-repo ).

$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.9BSD/root.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `..'
$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.10bsd.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `.' or `..'
rm: cannot remove `.' or `..'\n");

Cho dir/.dir/.., xem thay đổi này vào năm 1988 (BSD 4.3 Net / 1).

Cho đến ngày nay, rmFreeBSD (và các công cụ phái sinh như macOS) vẫn làm trống thư mục hiện tại hoặc thư mục gốc rm -rf ./hoặc rm -rf ../mặc dù (quan trọng đối với rm -rf .*/).

Hệ thống V

Tôi không có nhiều thông tin vì cả nguồn và nhị phân đều không có sẵn công khai cho các dẫn xuất Unix của AT & T sau V7. Trong hướng dẫn trực tuyến của mình, HPUX (dựa trên Hệ thống III) vẫn đề cập rằng nó chỉ cấm ..trong khi thực tế nó cấm cả hai đó là một dấu hiệu cho thấy ít nhất SysIII đã không cấm xóa .( chỉnh sửa : Bây giờ hãy xem mã nguồn SysIIIrm , đó là hầu như không thay đổi kể từ Unix V7).

Tất cả các hướng dẫn sử dụng trực tuyến khác mà tôi đã kiểm tra đề cập đến việc xóa .hoặc ..bị cấm dự kiến ​​là tuân thủ POSIX.

Solaris rmvẫn làm trống thư mục hiện tại hoặc cha mẹ trên rm -rf ./hoặc rm -rf ../.

GNU

Thay đổi sớm cho tập tin GNU có tất cả các thông tin lịch sử.

Mặc dù ban đầu không xóa .hoặc ..bị cấm, ..trước tiên bị cấm và sau đó cả hai (bao gồm dir/.), tất cả từ năm 1990 đến 1991.

khác

Như chúng ta đã thấy, trong zsh, việc mở rộng .*(hoặc bất kỳ toàn cầu) không bao giờ bao gồm .hoặc ..(ngay cả trong shchế độ mô phỏng). Do đó, phần rmdựng sẵn (mà bạn nhận được nếu bạn zmodload zsh/files) do đó không xử lý .hoặc ..đặc biệt. Vì vậy, với zshnội dung đó , bạn có thể rm -rf .hoặc rm -rf ..để trống .hoặc .., nhưng rm -rf .*sẽ không xóa .hoặc ...

Trong busybox rm, việc cấm xóa ...được thêm vào 0,52 (2001)


Điều lạ lùng là dường như chỉ định rằng rm -rf . /(lưu ý khoảng trắng) nên in hai cảnh báo (cho ./) và thoát, nhưng chúng tôi dường như nhận được một câu hỏi hỏi làm thế nào để phục hồi từ đó mỗi vài tháng.
Kevin

6
@Kevin Không phải tất cả các hệ thống đều tuân thủ POSIX và hạn chế thư mục gốc chỉ được thêm rõ ràng trong bản phát hành POSIX mới nhất.
jlliagre

@jlliagre Tôi thấy. GNU thường cố gắng triển khai POSIX (tất nhiên là các phần mở rộng) và tôi tưởng tượng họ muốn đưa cái này vào, nhưng nếu nó khá mới thì sẽ giải thích nó.
Kevin

2
@Stephane: bạn nói đúng, nhưng tôi vẫn thêm một câu "Có, nó có thể xảy ra! Nhưng ..." ở đầu câu trả lời của bạn, để mọi người chắc chắn biết rằng thực sự, trên một số (cũ hơn hoặc chỉ là không -POSIX tuân thủ) hệ thống, họ có thể xóa các thư mục mẹ. Tôi cố gắng luôn chỉ ra những khả năng đó (nghĩa là tôi cố gắng giữ an toàn, ngay cả khi điều đó khiến câu trả lời đôi khi khó đọc / nhớ hơn) ^^
Olivier Dulac

1
@ MartinSchröder, Trên BSD, nó đã được thêm vào đâu đó giữa 2.8BSD và 2.10BSD (trước đây chỉ ".." bị cấm như trong UnixV7) và giữa 3BSD và 4.3RENO. Trên các hệ thống SysV, nó ít rõ ràng hơn. Ví dụ, hướng dẫn sử dụng HPUX tuyên bố rằng nó chỉ cấm ".." nhưng thực tế, nó cấm cả "." và "..", đó chỉ là hướng dẫn không cập nhật.
Stéphane Chazelas
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.