Чому програмі unix mv не потрібен параметр -R (рекурсивний) для каталогів, але cp це потрібно?


58

Я завжди заплутався, коли потрібно використовувати cpабо mv: "чи потрібен мені -Rваріант при роботі з dir?" У GNU coreutils cpпотребує -Rі mvне потребує .

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

Чи знаєте ви якесь пояснення? Може, це було давно?


Додатковий запитання: чому розробники coreutils не роблять cpкопіювальні файли рекурсивно за замовчуванням?

Відповіді:


45

Каталог - це (концептуально) спеціальний "файл", який містить перелік імен та номери inode, на які вказують імена. Деякі назви можуть бути підкаталогами. Існує спеціальний запис, ..який вказує на батьківський каталог.

Отже, зрозуміти, змінити ім'я файлу досить просто: ви просто змінюєте ім’я у записі каталогу, нічого іншого. Це означає, що файл є насправді файлом, або це "файл", який використовується для зберігання вмісту іншого каталогу. Дійсно, однакова renameсистематична дзвінка робить і те, і інше.

Однак копіювання - це набагато менш тривіальна операція. Ви можете просто скопіювати каталог «файл», але тоді ви мали б два каталоги, де файли однакові (вони були б жорсткими посиланнями). Якби у вас була система, яка дозволяє жорсткі посилання на каталоги, це було б до цього, але оскільки жодна сучасна система не дозволяє це, принаймні, не викорінювати, ви повинні робити цю копію для кожного підкаталогу. Ви можете фактично запитати cpпро таку поведінку за допомогою cp -lR: -lдля жорсткого зв’язку, -Rдля цієї рекурсії.

Але залишати все пов'язане - це, мабуть, не те, що ви хочете. Натомість ви хочете cpскопіювати кожен файл. Це досить дорога операція: кожен файл повинен бути прочитаний в пам'яті та записаний на диск у другому місці. Насправді потрібно декілька системних викликів, щоб відкрити, прочитати, записати та закрити файли, і це потрібно повторити для кожного файлу.

Традиційні файлові системи працюють таким чином і на диску. Немає жодного способу скопіювати купу файлів, окрім як пройти кожен окремо та скопіювати його, і це типи файлових систем, які використовувались при розробці базових утиліт командного рядка.


є mvІНГ з однієї файлової системи в іншу таку ж «просто змінити ім'я в записі каталогу»?
rslnx

5
Ні, крос-файлова система - це те саме, що копія + видалення (дійсно, renameсистемна виклик не вдасться для крос-файлової системи). Не впевнений, чи історично mvнавіть підтримуються крос-фс-ходи.
дероберт

9
Я можу вам сказати, з прямого досвіду, не міркувань, що класика mvне підтримує крос-ходи. Він використовувався для того, щоб просто спробувати rename()і надрукувати повідомлення про помилку, якщо воно не вдалося. Я все ще пам’ятаю шоковане відчуття, яке мені довелося вперше випадково використати нову функцію. Чому цей телевізор займає так довго? О, це робить рекурсивну копію, яку я не мав намір!
Алан Карі

5
@RuslanKhusnullin Параметри командного рядка до звичайних команд дуже важко змінити через їх використання в скриптах оболонки. Хтось може залежати від поточної поведінки cp відмови від копіювання. Матеріали крос-фс, мабуть, вважали менш ймовірними, що спричинили поломку, хоча, як бачите, це все ж здивувало Алана.
дероберт

1
@derobert, цього не сталося (крос-файлова система mvпрацювала лише для окремих файлів на BSD 4.2 на VAX).
фонбранд

21

Почніть з того, щоб задати ще одне питання:

У чому різниця між cpі cp -R?

Ну а без -Rпрапора можна лише копіювати файли, тому що досить незвично, що хтось хоче нерекурсивно копіювати каталог: Нерекурсивна копія просто призведе до другого імені для каталогу, вказуючи безпосередньо на той самий каталог будова. Оскільки цього рідко хочуть люди, і насправді існує окрема програма, яка робить це ( ln), нерекурсивна копія каталогів заборонена.

Яка тоді може бути різниця між mvі mv -R?

mv a bпросто перейменовує один запис у каталозі, тож якщо каталог mvредагується, його вміст також автоматично переміщується. У цьому сенсі mvвже надається рекурсивна властивість, тобто "перейменування" всіх записів у перейменованому каталозі, наприклад, від a/1до b/1. mv, Що не робить цього, то є , який перейменовує каталог aз b, але тримає , a/1як a/1, це не те , що люди розуміють , коли вони відносяться до переміщення що - то: При переміщенні шафи, вміст шафи переміщаються , а також. Ця інша операція, переміщення каталогу без його вмісту, також уже доступна, вона називається mkdir.


2
Це так, я щойно думав cpі mvяк операції їх називають: "зробити копію" і "перемістити". Тож якщо я хочу зробити копію чашки кави, я очікував би ще одну чашку кави з такою ж начинкою (кавовий напій). Проблема полягає в тому, що інструменти призначені не для 'звичайних людей', а для оленів, які знають про структуру диска та файлової системи, а не для віртуальних сутностей, таких як файли та режими файлів.
rslnx

1
Добре структурована, аргументована відповідь.
Шпег

1
@RuslanKhusnullin Ваша аналогія з кавою працює cpі mvтеж - для її розуміння не потрібен якийсь рівень "дурості", просто основний здоровий глузд. Справжня копія чашки кави не є порожньою чашкою - ви повинні рекурсивно копіювати не тільки чашку, але і весь її вміст (каву) теж. Однак, коли ви пересуваєте чашку кави, вам не доведеться переміщувати вміст окремо - вміст рухається разом з контейнером природним чином.
jw013

1
@ jw013 Ви мене вразили тим, що "коли ви пересуваєте чашку кави, вам не потрібно переміщувати вміст окремо", це дійсно має сенс, дякую. Але це ще один шар абстракції. Я думаю, ви маєте на увазі "ставитися до файлу як до індексу", тоді як я думаю про файли, як послідовності байтів без метаінформації.
rslnx

6

Зазвичай, коли я плутаюся з логікою Unix, я дивлюся на Plan9, щоб побачити, як винахідники Unix впродовж років реалізували ті самі завдання, не затримуючись зворотної сумісності.

Тож Plan9 пропонує cpта mvінструменти для роботи лише з файлами.

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

Для копіювання режиму dircpє справді @{cd fromdir && tar c .} | @{cd todir && tar xT}(синтаксис оболонки rc)

Для переміщення режиму я думаю, що є тільки dircp d1 d2 && rm -r d1

Я думаю, що таке рішення щодо обмеження cpта лише mvдля файлових операцій (не dirs) приносить більшу чіткість дисковим операціям, а використання tarдля копіювання дерев файлів дуже зручно для розуміння та створення сценаріїв.

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