Почему программе Unix mv не нужна опция -R (рекурсивная) для каталогов, а cp это нужно?

58

Я всегда запутался, когда нужно использовать cpили mv: «Нужна ли -Rопция при работе с dir?» В GNU coreutils cpнужен -Rи mvне нужен .

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

Вы знаете какое-нибудь объяснение? Может быть, это было причиной давным-давно?


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

rslnx
источник

Ответы:

45

Каталог (концептуально) - это специальный «файл», который содержит список имен и номера инодов, на которые указывают эти имена. Некоторые из имен могут быть подкаталогами. Существует специальная запись, ..которая указывает на родительский каталог.

Итак, все понятно, изменить имя файла очень просто: вы просто меняете имя в записи каталога, больше ничего. Это определяет, является ли файл фактически файлом или «файлом», используемым для хранения содержимого другого каталога. Действительно, один и тот же renameсистемный вызов делает оба.

Копирование, однако, является гораздо менее тривиальной операцией. Вы можете просто скопировать каталог «file», но тогда у вас будет две директории, в которых файлы одинаковы (это будут жесткие ссылки). Если бы у вас была система, которая допускает жесткие ссылки на каталоги, то так и было бы, но поскольку ни одна современная система не позволяет этого, по крайней мере, без полномочий root, вы должны сделать эту копию для каждого подкаталога. Вы можете запросить cpэто поведение с помощью cp -lR: -lдля жесткой ссылки, -Rдля этой рекурсии.

Но оставить все связанное, вероятно, не то, что вы хотите. Вместо этого вы хотите cpскопировать каждый файл. Это довольно дорогая операция: каждый файл должен быть прочитан в память и записан на диск во втором месте. На самом деле для открытия, чтения, записи и закрытия файлов требуется несколько системных вызовов, и это должно повторяться для каждого файла.

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

derobert
источник
происходит ли mvпереход из одной файловой системы в другую "просто измените имя в записи каталога"?
rslnx
5
Нет, кросс-файловая система - это то же самое, что копирование + удаление (действительно, renameсистемный вызов не будет работать для кросс-файловой системы). Не уверен, что исторически mvдаже поддерживал перекрестные движения.
Дероберт
9
Я могу сказать вам, исходя из непосредственного опыта, а не спекуляций, что классика mvне поддерживала перемещения между устройствами. Раньше просто пытался rename()и печатать сообщение об ошибке, если это не удалось. Я до сих пор помню шокированное чувство, которое я испытал в первый раз, когда случайно использовал новую функцию. Почему этот фильм занимает так много времени? О, это рекурсивная копия, которую я не собирался!
Алан Карри
5
@RuslanKhusnullin Параметры командной строки для общих команд очень трудно изменить из-за их использования в сценариях оболочки. Кто-то может зависеть от текущего поведения cp. Материал о кросс-фс, вероятно, был оценен как менее вероятный, чтобы вызвать поломку, хотя, как вы можете видеть, он все же удивил Алана.
Дероберт
1
@ derobert, это не так (кросс-файловая система mvработала только для отдельных файлов на BSD 4.2 на VAX).
vonbrand
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
Хорошо структурированный, аргументированный ответ.
Spedge
1
@RuslanKhusnullin Вашего кофе аналогия работает cpи mvтоже - она не требует какого - либо уровня «nerdness» , чтобы понять, просто здравый смысл. Настоящая копия чашки кофе - это не пустая чашка - вы должны рекурсивно копировать не только чашку, но и все ее содержимое (кофе). Однако, когда вы перемещаете чашку кофе, вам не нужно перемещать содержимое отдельно - содержимое перемещается вместе с контейнером естественным образом.
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.

Для копирования dir есть dircpдействительно @{cd fromdir && tar c .} | @{cd todir && tar xT}(синтаксис rc shell)

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

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

rslnx
источник