Shell

‘rm .*’ 是否會刪除父目錄?

  • July 24, 2018

該表達式.*由 bash 擴展以包含目前目錄和父目錄:

$ 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 .*
. ..

如果我rm -rf .*使用 GNU bash 在我的 Debian 上執行,version 4.2.36(1)-release並且rm從 開始rm (GNU coreutils) 8.13,我會收到以下消息:

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

這是 GNU 的東西還是 POSIX?是否有任何 *nix 系統,上面的命令會靜默刪除...

另外,這是 shell 的安全功能還是rm命令本身的安全功能?

rm該實用程序的最新(截至 2017 年)版本的 POSIX 規範在這裡(以及以前的版本在那裡)並禁止刪除...

如果文件 dot 或 dot-dot 中的任何一個被指定為操作數的基本名稱部分(即最終路徑名組件),或者如果操作數解析為根目錄,則 rm 應將診斷消息寫入標準錯誤並且不執行任何操作更多使用此類操作數。

正如@jlliagre 所指出的,關於的部分/是SUSv4 中的一個補充。

我能找到的最古老的公開可用的 Unix 規範(XPF4 CAE rev2 (1994))已經指定.並且..無法刪除,儘管 GNU fileutils 更改日誌中的評論表明舊 POSIX 規範中已經存在這種情況。

請注意,它也適用於dir/..and ../,但某些實現(包括 UNIX 認證的實現,如 Solaris 11 和 macOS)仍然不能防止rm -rf ../or rm -rf .*/)。

歷史

早期的unices

在Unix V3 (1973) 中添加了-rto 選項,rm雖然它只是刪除目錄的內容,但您仍然需要使用它rmdir來刪除目錄。

這在 Unix V7 (1979 年,該版本還引入了 Bourne shell 並且大多數 Unices 派生自該版本)中發生了變化。rm -r現在也刪除了目錄,並且不會刪除..目錄樹。手冊頁指出:

禁止刪除文件..僅僅是為了避免無意中做類似rm -r .*.

(儘管有人可能會說這rm -r .*仍然是反社會的,因為它會刪除所有內容,因為.它包含在內)。

.儘管它不會取消連結...條目,但它仍然接受刪除。那麼,rm -r .清空目前目錄是一種有效的方法。

另請注意,保護措施僅適用於文字..參數,而不適用於dir/..or ./..。因此,rm -rf ./.*仍然會遞歸地刪除父目錄中的所有內容。

有趣的是,這已經解決了 glob 可以包含...擴展的錯誤/錯誤功能。這在 80 年代後期zsh(1990 年和2005 年)的 Forsyth shell(原始 Minix shell 和 pdksh 的基礎)中得到了修復,但在其他 shell 中沒有得到修復,特別是在需要擴展fish的 POSIX語言中包括if它們由(部分解決了問題,僅在 glob (除了那些)不包含or的情況下,並且使用,您可以通過做來解決它)。sh``.*``.``..``readdir()``bash``shopt -s dotglob``.xxx``.``..``ksh``FIGNORE='@(.|..)'

何時.添加確切的禁止並不總是很清楚,並且因每個 Unix 而異。下面的一些發現。

BSD

.在 2.9BSD (1983) 和 2.10BSD (1987) 之間以及 4.2BSD (1983) 和 4.3BSD (1986) 之間的某個時間添加了禁止 (請參閱unix -history-repo 中 1985 年的此更改時間戳)。

$ 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");

對於dir/.dir/..,請參見1988 年的這一變化(BSD 4.3 Net/1)。

迄今為止,rmFreeBSD(以及 macOS 等衍生產品)仍然會清空目前目錄或父目錄rm -rf ./rm -rf ../對於而言rm -rf .*/)。

系統五

我沒有太多資訊,因為 V7 之後的 AT&T Unix 衍生產品的原始碼或二進製文件都沒有公開可用。在其線上手冊中,HPUX(基於 System III)仍然提到它只禁止..而有效地禁止兩者,這表明可能至少 SysIII 沒有禁止刪除.編輯:現在查看SysIIIrm原始碼,它是自 Unix V7 以來幾乎沒有變化)。

我檢查過的所有其他線上手冊都提到刪除.或被..禁止,這應該是符合 POSIX 的。

Solarisrm仍會清空 或 上的目前目錄或父rm -rf ./目錄rm -rf ../

GNU

GNU fileutils的早期變更日誌包含所有歷史資訊。

雖然最初既沒有刪除.也沒有..被禁止,但在 1990 年至 1991 年期間,..先被禁止,然後又被禁止(包括)。dir/.

其他

正如我們所見,在 中, (或任何 glob)zsh的擴展從不包括or (即使在仿真模式下)。因此,內置函式(如果你得到)不會特別對待或特別對待。因此,使用該內置函式,您可以or清空or ,但不會刪除or 。.*``.``..``sh``rm``zmodload zsh/files``.``..``zsh``rm -rf .``rm -rf ..``.``..``rm -rf .*``.``..

在busybox中, 0.52(2001)增加rm了禁止刪除...

引用自:https://unix.stackexchange.com/questions/90073