Чи "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 .*на своєму Debian за допомогою GNU bash, 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 системи, де команда вище буде беззвучно видаляти .і ..?

Також, це безпечна функція оболонки або самої rmкоманди?


4
Я знаю , що це питання в контексті rm, але я подумав, що варто відзначити , що ви можете мати несподівані результати з chmod, chownі так далі при збігу .*.
Аарон Коплі

Відповіді:


59

Остання (на 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).

На сьогоднішній день, rmFreeBSD (і похідні, такі як 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 -rf . /(зверніть увагу на пробіл) слід надрукувати два попередження (для .та /) та вийти, але ми, мабуть, отримуємо запитання, як відновитись після цього кожні пару місяців.
Кевін

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 стверджує, що він забороняє лише "..", але фактично забороняє обидва "". і "..", це не лише оновлений посібник.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.