Why does MV(1) copy objects if permission to move denied?
Does mv
act as cp(1)
if permission for process to move denied?
If so, isn’t it against the rule do one thing and do it well?
The short answer is that it doesn’t.
perform actions equivalent to the
rename()
function
rename()
doesn’t copy content, it simply renames it on disk. It is a completely atomic operation that never fails partially complete.
That doesn’t tell the whole story, however. Where this effect can happen is when trying to move a file between devices: in that case, it isn’t possible to do the rename in the filesystem. To have the effect of moving, mv
first copies the source to the destination, and then deletes the source. In effect, mv /mnt/a/X /mnt/b/Y
is essentially equivalent to cp /mnt/a/X /mnt/b/Y && rm /mnt/a/X
. That’s the only way moving files between devices could work.
When mv
doesn’t have permission to delete that source file, an error will be reported, but at that point the copy has already occurred. It’s not possible to avoid that by checking the permissions in advance because of possible race conditions where the permissions change during the operation.
There’s really no way to prevent this possible eventuality, other than making it impossible to move files between devices at all. The choice to allow mv
between any source and destination makes things simpler in the general case, at the expense of odd (but non-destructive) behaviour in these unusual cases.
This is also why moving a large file within a single device is so much faster than moving it to another.