Почему `cp` и` rm` обрабатывают каталоги отдельно?

10

Почему инструменты любят cpи rmобрабатывают каталоги отдельно от обычных файлов? Они оба требуют, чтобы пользователь явно указал, что она хочет рекурсивное поведение, иначе они вообще не будут иметь дело с каталогами.

Мое первое взаимодействие (некоторое время назад) с компьютерами происходило в среде Windows / GUI / point-and-click / drag-and-drop, и всегда казалось естественным, что эти операции будут вести себя одинаково, независимо от цели.

Такое поведение особенно расстраивает меня, когда я даю команды с подстановочными знаками. Что если я хочу удалить все в каталоге ( *), кроме непустых подкаталогов ?

Я могу только представить, что это какая-то функция безопасности, которая не позволяет пользователю выстрелить себе в ногу, но это противоречит моему пониманию некоторых принципов Unix:

  • Unix обычно не защищает пользователя от себя. Он всегда предполагал, что пользователь знает, что она делает.
  • Для Unix все это файл. Разве каталог не просто еще один файл? Почему к ним относятся по-разному?

Мои вопросы:

  • Это поведение обусловлено техническими ограничениями или это осознанный выбор?

И в случае последнего,

  • Есть ли исторические описания причин, которые мотивировали этот выбор?
rahmu
источник
По rmкрайней мере, если вы хотите, чтобы игнорировать разницу между файлами и каталогами, вы можете поместить в вашем ~/.bashrcфайле: alias rm='rm -r'.
BenjiWiebe
1
См. Также другой, но связанный вопрос unix.stackexchange.com/questions/46066/…
derobert
1
Вы не можете сравнить cp и rm с файловым менеджером Windows. Запустите cmd.exe и попробуйте скопировать и удалить и сравнить поведение.
ot--

Ответы:

11

Почему Дероберт почему для программы Unix mv не нужна опция -R (рекурсивная) для каталогов, а для cp она нужна? в основном отвечает на ваш вопрос: копирование или удаление обычного файла отличается от выполнения той же операции с каталогом, потому что для каталога вам нужно обработать все содержащиеся в нем файлы. Следовательно операция в корне отличается.

Также стоит отметить, что есть специальная утилита, rmdirкоторая может работать только с пустыми каталогами. Без проверки фактов это приводит к выводу, что, возможно, первоначально rmбыло возможно удалить только не-каталоги, а глубокое удаление должно было быть достигнуто путем рекурсивного использования, rmчтобы очистить каталоги, а затем rmdirудалить их.

peterph
источник
rmdirтакже имя системного вызова, который использовался для удаления каталога. Каталог должен быть пустым для системного вызова, а утилита с таким же именем просто "front-end", аналогично unlinkкоманде и утилите.
Иордания
Именно - это то, что заставляет меня поверить, что первоначально, rmвозможно, вообще не удалось удалить каталоги (потому что утилиты командной строки часто являются просто относительно простыми обертками вокруг системных вызовов).
Петер
Заголовок моего вопроса может ввести в заблуждение мысль, что я спрашиваю о технических деталях. Я спрашивал, является ли это осознанным выбором. Интересно, я один думаю, что с точки зрения конечного пользователя это поведение противоречиво. Я принимаю ваш ответ, потому что он косвенно отвечает на мой вопрос: технические ограничения во внутренних компонентах Unix (на уровне системного вызова), по-видимому, являются источником такого поведения, и наследие, вероятно, мешает нам сделать это любым другим способом сегодня. Разве «простые обертки вокруг системных вызовов» не должны дать нам более разумное поведение?
Рахму
2
Для конечного пользователя POV это действительно странно, но вы на самом деле спрашивали о причинах. :) Что касается оберток - все зависит от того, насколько они «просты» (и что вы еще хотите назвать «простыми»). Modern, rmбезусловно, не просто оболочка (он может одновременно удалять файлы mroe и каталоги). Если вам не нравится давать ему эту -rопцию, используйте псевдонимы вашей оболочки или создайте свою собственную обертку, которая поместит ее на место (что будет медленнее, но не зависит от используемой вами оболочки).
Петер
2

В некоторых версиях UNIX man-страница rm определяет ее как команду для удаления связи с файлом.
В UNIX файлы - это объекты в файловой системе, называемые Inodes, без имен или расположения, кроме идентификатора в файловой системе. Их имена являются ссылками на них в различных каталогах, которые представляют собой тип файла, который индексирует файлы (или каталоги, поскольку они являются файлами), которые перечислены в нем.
При отмене связывания файла счетчик ссылок файла уменьшается, а когда он достигает 0, он фактически удаляется, поскольку файловая система помечает его как свободный, а его блоки / экстенты также помечаются как свободные.

Если у вас была возможность создать каталог без предварительного отсоединения файлов внутри него, вы достигнете точки, когда у вас есть inode-ы, на которые есть ссылки в вашей файловой системе, но к которым нельзя получить доступ никакими обычными способами.
Поскольку существует ссылка на них в соответствии с их количеством ссылок, они не помечаются как удаленные и становятся потерянными файлами.
Это становится еще более сложным, когда потерянные «файлы» являются каталогами, и поэтому увеличивает потенциальный объем потерянного хранилища в файловой системе.

Таким образом, rm -r был добавлен в качестве функции, облегчающей жизнь пользователей UNIX, за счет стандартного «духа UNIX», поскольку он более сложен, чем классические утилиты UNIX, так как он спускается в каталоги и удаляет файлы внутри,

Кроме того, в ранние времена UNIX системы не имели большого объема памяти, а отображение рекурсивной структуры каталога приводило к снижению производительности, и иногда было невозможно обойтись без разделения работы.

cp, читает файл и копирует его, блок за блоком. Если бы он копировал каталог так же, как и файл, он добавил бы ссылки на файлы внутри, не увеличивая их счетчик ссылок, что могло бы привести к несогласованности данных (при чтении / записи в инод, чьи блоки помечены как свободные с момента их исходный индекс был удален), потерянные данные - поскольку удаление последней (известной) ссылки на файл может привести к повторному использованию его номера индекса.

Для группы tl; dr:
каталоги в UNIX - это тип файла, это правда, но поскольку информация в них обрабатывается системой по-разному, так как это метаданные файловой системы, команды, управляющие файлами, не могут работать с каталогами без изменить их поведение, чтобы манипулировать зависимыми метаданными.

Диди Коэн
источник