Остання (на 2017 рік) версія специфікації POSIX для rm
утиліти знаходиться тут (і попередня там ) і забороняє видалення .
та ..
.
Якщо будь-який із файлів точка або крапка вказаний як частина базового імені операнда (тобто компонент кінцевого імені шляху) або якщо операнд вирішить до кореневого каталогу, rm повинен написати діагностичне повідомлення на стандартну помилку і нічого не робити більше з такими операндами.
Як зазначає @jlliagre, частина про /
- це доповнення в SUSv4.
Найстаріший загальнодоступними Unix специфікації , які я зміг знайти ( XPF4 CAE rev2 (1994)), вже вказувалося , що .
і ..
не можуть бути видалені, хоча коментарі в ГНУ FileUtils журналу змін припускають , що це був вже випадок в старих POSIX специфікації.
Зауважте, що це стосується dir/..
і іншого ../
, але деякі реалізації (включаючи сертифіковані UNIX, такі як Solaris 11 та macOS) все ще не захищають від rm -rf ../
або rm -rf .*/
).
історія
Ранні уніці
У Unix V3 (1973) -r
опція rm
була додана, хоча вона видаляла лише вміст каталогів, вам все одно потрібно було б використовувати rmdir
для видалення каталогів.
Це змінилося в Unix V7 (1979, випуск, який також представив оболонку Bourne і з якої виходить більшість Unices). rm -r
тепер видалені каталоги також не видалять ..
дерево каталогів. На сторінці чоловіка зазначено:
Забороняється видаляти файл ..
лише для уникнення антисоціальних наслідків випадкового вчинення чогось подібного rm -r .*
.
(хоча можна стверджувати, що rm -r .*
це все ще антисоціально, оскільки він видаляє все, тому що .
включено).
Він все-таки прийняв видаляти, .
хоча це не від’єднає .
або ..
записи. Тож rm -r .
був ефективним способом спорожнення поточного каталогу.
Також зауважте, що гарантія була лише для буквального ..
аргументу, а не для dir/..
або ./..
. Отже, rm -rf ./.*
все одно видалятиметься все з батьківського каталогу рекурсивно.
Цікаво бачити, що це вже було вирішити помилку / неправильну функцію, завдяки якій глобуси могли б включати .
та ..
в їх розширення. Це було зафіксовано у оболонці Forsyth (основа для оригінальної оболонки Minix та pdksh) наприкінці 80-х, zsh
(1990) та fish
(2005), але не іншими оболонками та, зокрема, не sh
мовою POSIX, яка вимагає розширення .*
для включення, .
і ..
якщо вони повертаються readdir()
( bash
вирішує проблему частково лише shopt -s dotglob
там, де глобуси (крім .xxx
тих) не містять .
або ..
, і ksh
, ви можете виправити це, виконавши FIGNORE='@(.|..)'
).
Коли .
було додано саме заборону заборони , не завжди зрозуміло і змінюється в залежності від кожного Unix. Кілька висновків нижче.
BSD
Забороняючи з .
додавали то між 2.9BSD (1983) і 2.10BSD (1987) , а також між 4.2BSD (1983) і 4.3BSD (1986) (див це зміна датуються 1985 unix-історії-репо ).
$ 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).
На сьогоднішній день, rm
FreeBSD (і похідні, такі як macOS) все ще вимиває поточний або батьківський каталог після rm -rf ./
або rm -rf ../
хоча (має значення для rm -rf .*/
).
Система V
Я не маю багато інформації, оскільки ні джерело, ні двійкові дані не є загальнодоступними для похідних AT&T Unix після V7. У своєму онлайн-посібнику HPUX (на основі System III) все ще згадує, що він забороняє лише ..
той час, коли ефективно він забороняє обидва, що є свідченням того, що, мабуть, принаймні SysIII не заборонив видалення .
( редагувати : Тепер, дивлячись на вихідний код SysIIIrm
, це практично незмінний від Unix V7).
Усі інші онлайн-посібники, які я перевірив, згадують про видалення .
або ..
заборонено, що, як очікується, відповідатиме POSIX.
Solaris rm
все ще очищає поточний або батьківський каталог на rm -rf ./
або rm -rf ../
.
GNU
Рано змін для FileUtils GNU має всю історичну інформацію.
Хоча спочатку ні видалення, .
ні ..
заборонялося, ..
спершу було заборонено, а потім і те й інше (у тому числі dir/.
), і все це між 1990 та 1991 роками.
інший
Як ми бачили, zsh
розширення .*
(або будь-якого глобуса) ніколи не включає .
або ..
(навіть у sh
режимі емуляції). Тому rm
вбудований (який ви отримуєте, якщо ви zmodload zsh/files
), отже, не лікує .
або ..
спеціально. Отже, із zsh
вбудованим файлом ви можете rm -rf .
або rm -rf ..
спорожнити .
або ..
, але rm -rf .*
не видалити .
або ..
.
У службовій скриньці rm
заборона видалення .
та ..
була додана в 0,52 (2001 р.)
rm
, але я подумав, що варто відзначити , що ви можете мати несподівані результати зchmod
,chown
і так далі при збігу.*
.