Как решить, что mv перемещается в каталог, а не заменяет каталог?

18

Скажи, у меня есть каталог /hello.

Тогда я делаю mv /hello /hello2.

Я вхожу /helloв /hello2/hello? Или я двигаюсь /helloк /hello2?

Кажется, что когда я делаю что-то подобное, я получаю противоречивые результаты.

user4951
источник
1
В каком случае результат противоречив? Кажется, что всякий раз, когда целевой каталог существует, он перемещается в целевой каталог, в противном случае он переименовывается.
Jmathew
Это противоречиво. Та же команда должна сделать то же самое. Это означает, что команда неоднозначна.
user4951
Это не совсем противоречиво, потому что действует последовательно в контексте. Хотя я вижу, как это сбивает с толку, но чем больше я об этом думаю, тем более должна быть команда, чтобы работать для всех сценариев.
Jmathew
Я бы скорее сказал, что так оно и задумано, и это тоже логично ... если вы используете mvс файлами, он делает то же самое. Просто переименуйте. Но mvс каталогами. Нецелесообразно удалять весь каталог с подкаталогом из-за одной mvкоманды, которая не сейф. поэтому он перемещен как test1/test2. но если вы все еще хотите его получить, напишите a, aliasкоторый проверяет, является ли данный параметр каталогом, а затем выполните команду rm -rf the directory и используйте mvкоманду, но используйте ее на свой страх и риск.
harish.venkat
Я подозреваю, что ваш пример основан на неправильном воспоминании о том, что произошло в прошлом, на основе «Кажется, я делаю что-то подобное». Если оба /helloи /hello2являются каталогами, то я заметил, что cp /hello /hello2это тот, который несовместим. В зависимости от того, какая комбинация конечных слэшей существует, иногда содержимое /helloкопируется в /hello2, а иногда копируется сам каталог.
Изката

Ответы:

16

mv a bпытается перейти aв каталог bif bили символическую ссылку на каталог. В противном случае он будет переименовывать (или копировать и удалять, если в других файловых системах) aв b.

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

mv file dir/

или

mv file dir/.

Если dirне существует, вы получите сообщение об ошибке, и оно не будет переименовано fileв dir.

Если, с другой стороны, вы хотите сделать это, renameне беспокоясь о том, существует ли файл назначения как каталог или нет, с помощью GNU mv вы можете сделать:

mv -T file dest

В этом случае fileне будет перемещен в , destесли destэто каталог. Однако, если оба fileи destявляются каталогами и destпустыми, fileбудут переименованы dest(и оригинал destудален). Если оба являются каталогами и destне пустые, mv -Tбудут жаловаться.

То же самое, если fileи неdest являются каталогами (включая символические ссылки, включая символические ссылки на каталоги), будет переименовано (хотя вы получите приглашение, если у вас нет разрешения на запись ), а оригинал будет удален. Есть разница с тем, где есть символическая ссылка на каталог. С , переименовывается , но без , перемещается в каталог, на который указывает .filedestdestdestmv file destdest-Tfiledest-Tfiledest

Таким образом, чтобы подвести итог, после mv -T file dest, либо fileбудет переименован destили вы получите сообщение об ошибке (или приглашение). Если команда выполнена успешно, оригинал dest, если он существовал ранее, будет удален.

Стефан Шазелас
источник
14

Это полностью зависит от того, существует ли уже каталог с именем / hello2 или уже существует.

Если / hello2 существует И является каталогом, то перемещение всегда будет перемещать / hello в / hello / hello2

Если / hello2 не существует, команда move всегда переименовывает / hello в / hello2

Если / hello2 существует, И является файлом, вы получите сообщение об ошибке "не может перезаписать не-каталог" hello2 "с каталогом" hello ".

Дон симон
источник
3

Я пробовал это

mkdir test1
mv -v test1 test2
output:`test1' -> `test2'
mkdir test1
mv -v test2 test1
output: `test2' -> `test1/test2'
touch test2
output:mv: cannot overwrite non-directory `test2' with directory `test1'

надеюсь, это все объясняет. -vэто подробный режим.

harish.venkat
источник