「rm。*」は親ディレクトリを削除しますか?


53

.*は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)-releasermからrm (GNU coreutils) 8.13このメッセージが表示されます。

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

これはGNUのものですか、それともPOSIXですか?上記のコマンドが静かに削除する* nixシステムは.あり..ますか?

また、これはシェルまたはrmコマンド自体の安全機能ですか?


4
私はこの質問が文脈rmにあることを知っていますが、一致するときchmodchown、などで予期しない結果が生じる可能性があることに言及する価値があると思いました.*
アーロンコプリー

回答:


59

最新のためのPOSIX仕様のバージョン(2017年現在)rmユーティリティがあり、ここで(と前のそこ)との削除を禁止.して..

ファイルのドットまたはドットドットのいずれかがオペランドのベース名部分(つまり、最終パス名コンポーネント)として指定されている場合、またはオペランドがルートディレクトリに解決される場合、rmは診断メッセージを標準エラーに書き込み、何もしません。そのようなオペランドの場合はもっと。

@jlliagreが述べたように、約の部分/はSUSv4の追加です。

GNU fileutilsのchangelogのコメントは古いPOSIX仕様のケースに既にあることを示唆しているが、私が見つけることができる最も古い公に利用可能なUnix仕様(XPF4 CAE rev2(1994))は既にそれを指定し...削除できない。

それが適用されることに注意dir/..して../も、しかし(Solarisの11とMacOSのようなUNIX認定のものを含む)いくつかの実装はまだに対する保護をしませんrm -rf ../rm -rf .*/)。

歴史

初期の大学

-rオプションrmはUnix V3(1973)で追加されましたが、ディレクトリのコンテンツを削除するだけでしたが、ディレクトリを削除するにはまだ使用rmdirする必要があります。

Unix V7(1979年、Bourneシェルも導入し、ほとんどのUnicesが派生したリリース)で変更されました。rm -rディレクトリも削除され、..ディレクトリツリーが削除されなくなりました。manページの状態:

ファイルを削除することは..単にのようなことを不注意に行うことの反社会的結果を避けるために禁止されていますrm -r .*

(1は、それが主張するかもしれませんがrm -r .*、まだある反社会的ので、それがすべてを削除として.含まれています)。

それはまだ取り除くために受け入れなかった.、それは解除しませんけれども...のエントリを。したがってrm -r .、現在のディレクトリを空にする効果的な方法でした。

また、セーフガードはリテラル..引数のみであり、dir/..またはではないことに注意してください./..。したがって、rm -rf ./.*親ディレクトリのすべてを再帰的に削除します。

それはそれはグロブを含めることができたことにより、バグ/設計ミス回避するためにすでにあったと見るのは興味深いです.し、..その展開では。フォーサイスシェル80年代後半で(元のMinixシェルとpdkshのための基礎)、中に固定されたことzsh(1990)とfish(2005)ではなく、他のシェルを、特にPOSIXのではないshの拡充が必要で言語が.*含まれるように.して..いる場合によって返されますreaddir()(グロブ(1つを除く)がorを含まないbash部分でのみ問題に対処し、で、を実行することで修正できます)。shopt -s dotglob.xxx...kshFIGNORE='@(.|..)'

正確に禁止すること.もいつ追加されたかは必ずしも明確ではなく、各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ネット/ 1)。

これまでのところ、rmFreeBSD(およびmacOSのような派生物)は、現在または親ディレクトリを空にします(rm -rf ./またはrm -rf ../重要ですrm -rf .*/)。

システムV

V7以降のAT&T Unix派生物については、ソースもバイナリも公開されていないため、あまり情報がありません。同社のオンラインマニュアルでは、(システムIIIに基づく)、HP-UXはまだそれだけ禁止であると述べて..効果的にそれはおそらく、少なくともSysIIIがの削除禁止していないことを示していた両方禁止しながら.編集今見て:SysIII rmソースコードは、それはですUnix V7以降実質的に変更されていません)。

私がチェックした他のすべてのオンラインマニュアルでは、POSIX準拠であると思われる削除.または..禁止が言及されています。

Solarisのはrmまだ時に電流または親ディレクトリを空にしrm -rf ./たりrm -rf ../

GNU

GNU fileutils初期の変更ログには、すべての履歴情報が含まれています。

もともとはどちらも削除しないものの.、または..禁止された、..最初にして、両方(を含む禁止されたdir/.すべての1990年と1991年の間、)。

その他

で見たように、zshでの拡張.*(または任意のグロブ)には、.または..shエミュレーションモードでも)含まれることはありません。したがって、rmビルトイン(を使用した場合に取得されますzmodload zsh/files)は...特別な扱いをしません。だから、それをzsh組み込み、あなたができるrm -rf .か、rm -rf ..空にする...が、rm -rf .*削除されません...

busyboxの内rmの削除の禁止.及び..0.52(2001)に添加しました


奇妙なことに、rm -rf . /(スペースに注意して)2つの警告(./)を出力して終了するように指定しているようですが、数か月ごとにそれから回復する方法を尋ねる質問があるようです。
ケビン

6
@KevinすべてのシステムがPOSIXに準拠しているわけではなく、ルートディレクトリの制限は最新のPOSIXリリースでのみ明示的に追加されました。
jlliagre

@jlliagreなるほど。GNUは通常POSIX(もちろん拡張機能)を実装しようとしますが、これを入れたいと思うでしょうが、かなり新しいものであればそれで説明できます。
ケビン

2
@Stephane:あなたは正しいですが、答えの冒頭に大きな「はい、それは起こる可能性があります!...」を追加して、人々が間違いなくそれを知っているようにします-POSIX準拠)システム、親ディレクトリを削除できます。私は常にそれらの可能性を指摘しようとしています(つまり、答えが読みにくくなる場合がありますが、安全な側に留まるようにしています)^^
オリビエデュラック

1
@MartinSchröder、BSDでは、2.8BSDと2.10BSDの間(UnixV7のように ".."のみが禁止されていた前)および3BSDと4.3RENOの間に追加されました。SysVシステムでは、それほど明確ではありません。たとえば、HPUXマニュアルでは、「..」のみを禁止しているが、実際には両方の「。」を禁止していると主張しています。そして「..」、それは最新のものではないマニュアルだけです。
ステファンシャゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.