При перемещении текущего каталога я получаю сообщение «mv: невозможно переместить `.' в `../dir/.': устройство или ресурс заняты»

При перемещении текущего каталога я получаю сообщение «mv: невозможно переместить `.' в `../dir/.': устройство или ресурс заняты»
$ mv . ../general/
mv: cannot move `.' to `../general/.': Device or resource busy

Означает ли это, что текущий каталог является занятым устройством или ресурсом и не может быть перемещен? Почему?

решение1

Вы не можете переместить каталог, в котором находитесь. Текущий процесс — это тот, который его занимает.

Вместо этого поднимитесь на один уровень выше и назовите предыдущий текущий каталог, чтобы переместить его в целевой каталог.

решение2

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

$ pwd && echo $PWD && realpath .
/home/jimmij/tmp
/home/jimmij/tmp
/home/jimmij/tmp
$ mkdir tmp1 tmp2
$ mv tmp1/. tmp2/
mv: cannot move ‘tmp1/.’ to ‘tmp2/.’: Device or resource busy

не работает, но

cd tmp1
mv ../tmp1 ../tmp2

работает отлично, так что на самом деле выможетпереместить текущий каталог, хотя некоторые команды могут быть перепутаны после этой операции:

$ pwd && echo $PWD && realpath .
/home/jimmij/tmp/tmp1
/home/jimmij/tmp/tmp1
/home/jimmij/tmp/tmp2/tmp1
$ cd .
$ pwd && echo $PWD && realpath .
/home/jimmij/tmp/tmp2/tmp1
/home/jimmij/tmp/tmp2/tmp1
/home/jimmij/tmp/tmp2/tmp1

Похожая история с .., т.е. родительским каталогом.

Другими словами, каждый каталог должен содержать как минимум два элемента: .и ... Вы не можете перемещать или удалять их.

решение3

Причина, по которой вы получаете это сообщение:

mv: невозможно переместить .' to../general/.': Устройство или ресурс занят

из-за того, как ., и ..работают в дополнение к mv. Когда вы перемещаете что-либо в Unix, mvкоманда пытается отсоединить все, что ссылается на inode элемента, который вы пытаетесь переместить. В этом случае это будет inode того каталога, на который .ссылается.

"Символы/ссылки" .и ..ссылаются на inodes и в некотором смысле являются особенными. Вы можете прочитать об их истории здесь, в U&L Q&A под названием:Почему новый каталог имеет количество жестких ссылок, равное 2, до того, как в него что-либо будет добавлено?Если вы когда-либо смотрели на недавно созданный каталог, вы заметили, что он всегда начинается с количества ссылок, равного 2. Причина кроется в существовании .и ...

$ mkdir adir

$ ls -l | grep adir
drwxrwxr-x. 2 saml saml 4096 Oct  5 08:02 adir

$ ls -la adir/
total 8
drwxrwxr-x. 2 saml saml 4096 Oct  5 08:02 .
drwxrwxr-x. 3 saml saml 4096 Oct  5 08:02 ..

ПРИМЕЧАНИЕ:Ссылка на lsвыходные данные, если вам что-то неясно, находится здесь, в этом U&L Q&A под названием:Что означают поля в выводе ls -al?

Так что это не имена реальных каталогов, а "символы/ссылки", которые ссылаются на них. Поэтому их нужно отвязать, прежде чем они смогут mv.

Поскольку ваша команда использует ., ее нельзя отменить командой mv, отсюда и сообщение: «Устройство или ресурс занят».

Рекомендации

решение4

Linux запрещает переименование любого пути, заканчивающегося на компонент .или .., возвращая ошибку EBUSY; следующее также не будет выполнено:

$ mkdir a a/aa
$ mv a/aa/.. b
mv: cannot move ‘a/aa/..’ to ‘b/..’: Device or resource busy

Код для этого находится в namei.c::renameat. Последний компонент имени пути при передаче различным функциям должен иметь тип LAST_NORM, а не LAST_DOTили LAST_DOTDOT.

FreeBSD возвращает ошибку EINVAL в каждом из этих случаев.


Мы можем только догадываться, почему существует такое ограничение.

Функция rename() завершится ошибкой, если:
...
[EBUSY] Каталог, названный old или new, в настоящее время используется системой или другим процессом, и реализация считает это ошибкой.

Можно было бы считать ., что в данный момент используется процессом. Но учтите, что Linux допускает следующее, поэтому каталог, который просто используется каким-то процессом, не является достаточным для renameсбоя:

$ mkdir /tmp/t
$ cd /tmp/t
$ mv /tmp/t /tmp/t1
$ /bin/pwd
/tmp/t1

Причиной запрета на переименование ., ..вероятно, является «снижение путаницы среди пользователей».

  • .обычно является жесткой ссылкой на запись каталога в его родителе и является несколько особенным в том, что процесс всегда может открыться .для доступа к своему текущему рабочему каталогу. Возможность переименовать его была бы контрпродуктивной.
  • ..обычно является жесткой ссылкой на родительский каталог и имеет несколько особенностей, поскольку открывающийся процесс ..получит родительский каталог (или сам каталог, если это точка монтирования). Возможность переименовать его была бы контрпродуктивной.

Linux также запрещает rmdirпуть, последний компонент которого ..(ENOTEMPTY) или .(EINVAL). FreeBSD возвращает ошибку EINVAL для каждого из них.Стандарт POSIX для rmdirесть это:

Функция rmdir() завершится ошибкой, если:
...
[EINVAL] Аргумент пути содержит последний компонент, являющийся точкой.

Связанный контент