Чому `cp` і` rm` розглядають каталоги окремо?


10

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

Моя перша взаємодія (деякий час назад) з комп’ютерами була в середовищі Windows / GUI / точка-і-натискання / перетягування, завжди здавалося природним, що ці операції будуть вести себе однаково, незалежно від цілі.

Така поведінка мене особливо засмучує, коли я даю команди за допомогою малих символів. Що робити, якщо я хочу видалити все в каталозі ( *), крім не порожніх підкаталогів ?

Я можу лише уявити, що це якась функція захисту, яка не дозволяє користувачеві стріляти в ногу, але це суперечить моєму розумінню кількох принципів Unix:

  • Unix зазвичай не захищає користувача від себе. Завжди вважалося, що користувач знає, що вона робить.
  • Для Unix все - це файл. Чи не каталог лише інший файл? Чому до них ставляться по-різному?

Мої запитання:

  • Це поведінка випливає з технічного обмеження чи це свідомий вибір?

А у випадку останнього,

  • чи існують історичні відомості про причини, які мотивували цей вибір?

За rmпринаймні, якщо ви хочете, щоб ігнорувати різницю між файлами і каталогами, ви можете помістити в вашому ~/.bashrcфайлі: alias rm='rm -r'.
BenjiWiebe

1
Дивіться також інше, але пов'язане з цим питання unix.stackexchange.com/questions/46066/…
derobert

1
Ви не можете порівняти cp та rm з файловим менеджером Windows. Запустіть cmd.exe і спробуйте скопіювати та розділити та порівняти поведінку.
ott--

Відповіді:


11

Derobert's Чому програма unix mv не потребує опції -R (рекурсивна) для каталогів, але cp це потрібна? в основному відповідає на ваше запитання: копіювання або видалення звичайного файлу відрізняється від виконання однієї і тієї ж операції з каталогом, оскільки для каталогу потрібно обробити всі файли, що містяться в ньому. Отже, операція принципово інша.

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


rmdirтакож ім'я системного виклику, який використовувався для видалення каталогу. Каталог повинен бути порожнім для системного виклику, а утиліта з тим самим іменем просто "передній", подібно до unlinkкоманди та утиліти.
Йорданм

Саме це - саме те, що приводить мене до думки, що спочатку, rmможливо, взагалі не вдалося видалити каталоги (тому що утиліти командного рядка часто є лише відносно простими обгортками навколо системних викликів).
петерф

Назва мого питання може ввести в оману, якщо я думаю, що я запитую про технічні деталі. Я запитував, чи це навмисний вибір. Цікаво, чи я єдиний, хто вважає, що з точки зору кінцевого споживача така поведінка суперечлива. Я приймаю вашу відповідь, тому що вона опосередковано відповідає на моє запитання: технічні обмеження у внутрішніх системах Unix (на рівні системного виклику), здається, є джерелом такої поведінки, і спадщина, ймовірно, заважає нам робити це будь-яким іншим способом сьогодні. Чи не "прості обгортки навколо системних дзвінків" не повинні давати нам більш розумної поведінки?
rahmu

2
З боку кінцевого споживача POV, це здається дивним, але ви насправді запитували про причини. :) Що стосується обгортки - все залежить від того, наскільки вони "прості" (і що ви ще хочете назвати "простими"). Сучасний rmнапевно - це не просто проста обгортка (вона здатна видаляти файли mroe відразу, а також каталоги). Якщо вам не подобається надавати їй -rможливість, скористайтеся функцією згладжування оболонки або створіть власну обгортку, яка поставить її на місце (що буде повільніше, але незалежно від оболонки, яку ви використовуєте).
петерф

2

У деяких ароматах UNIX, man-сторінка rm вказує її як команду від’єднати файл.
У UNIX файли - це об'єкти у файловій системі під назвою Inodes, без імен та місцезнаходження крім ідентифікатора у файловій системі. Їх імена - це посилання на них у різних каталогах, які є типом файлу, який індексує файли (або каталоги, оскільки вони є файлами), які перераховані в ньому.
При від’єднанні файлу кількість посилань на файл зменшується, а коли він досягає 0, він фактично видаляється, оскільки він позначається як файлова система як вільний, а його блоки / розширення також позначаються вільними.

Якщо ви мали змогу запустити каталог, не сполучаючи файли всередині нього, ви дістанетесь до пункту, де у вашій файловій системі є посилання на індекси, але не можна отримати доступ будь-яким звичайним способом.
Оскільки в них є посилання на їх кількість, вони не позначаються як видалені та втрачаються файлами.
Це стає ще складнішим, коли втрачені "файли" - це каталоги, і як таке збільшує потенційну кількість втраченого сховища у файловій системі.

Таким чином, rm -r було додано як особливість полегшити життя користувачів UNIX за рахунок стандартного "духу UNIX", оскільки він складніший за класичні утиліти UNIX, оскільки він спускається до каталогів та видаляє файли всередині,

Крім того, в ранні часи UNIX системи не мали великої кількості пам'яті, і для відображення рекурсивної структури каталогу було передбачено покарання за продуктивність, а іноді це було неможливо, не розбивши роботу.

cp, читає файл і копіює його, блокуйте за блоком. Якщо б було скопіювати каталог такий же, як і у файлі, воно додало б посилання на файли всередині, не збільшуючи їх посилання, що може призвести до непослідовних даних (якщо читати / записувати до inode, котрі блоки позначені як вільні, оскільки їх оригінал inode був видалений), втрачені дані - оскільки видалення останньої (відомої) посилання на файл може призвести до повторного використання його номера inode.

Для tl; dr crowd:
Каталоги в UNIX - це тип файлу, це правда, але оскільки інформація всередині них обробляється по-різному, оскільки це метадані файлової системи, команди, що управляють файлами, не можуть працювати в каталогах без зміни в їх поведінці, щоб також маніпулювати залежними метаданими.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.