mv
无法将目录移动到具有同名目录的目标:
$ mv fortran/ imperative_PLs/
mv: cannot move ‘fortran/’ to ‘imperative_PLs/fortran’: Directory not empty
为什么
mv
在这种情况下不起作用?可以从系统调用来解释吗mv
? (比较一下rsync
可以)为什么
mv
设计在这种情况下不起作用?其理由或要点是什么?
答案1
mv
并且rsync
不是类似的程序。特别是,mv
经常尝试简单地重命名对象。如果它位于同一文件系统中,则它根本不复制内容。
如果您还没有imperative_PLs/fortran
,那么mv
将采用现有fortran
目录并将其重命名为树中的该点。
但是您在该位置已经有一个目录(包含内容)。由于名称只能引用单个对象,因此必须删除或重命名现有目录。 mv
假设您不想执行任何操作并中止。
rsync
相反,复制其中的各个文件和其他内容fortran
并将它们放入现有imperative_PLs/fortran
目录中。
相反rename
,这种行为似乎更容易理解。
答案2
mv
在这种情况下不起作用,因为它的设计目的不是这样做。系统调用(可能)是- 移动到相同的文件系统:(
rename
原来link
和unlink
) - 跨文件系统移动:递归文件复制,然后递归
unlink
- 移动到相同的文件系统:(
意见:我认为这与其说是设计的,不如说是设计的不是工作,因为它不是为处理这个用例而设计的。对于一个旨在做好一件事的“简单”工具,您需要提供一组开关来指示
mv
要采取以下哪一个操作路径:- 出现错误时退出,如当前实施中所示
- 合并时,如果文件已存在则抛出错误
- 合并,替换任何已存在的目标文件
cp
如果合并/替换操作是您想要的,您可以使用后跟rm
或使用文件树复制实用程序之一来轻松实现它tar
,pax
等等。
答案3
mv
实际上是rename
在幕后。
如果将一个文件移动到另一个文件,mv
则假设您知道自己在做什么并覆盖目标文件。
如果将一个目录移动到另一个目录,mv
则假设您要保留原始目录的基本名称并在目标目录上创建它。如果目标端尚不存在具有该名称的目录,或者具有该名称的目录存在但为空,则操作成功。
但是,如果目标目录已经存在并且不为空,则这不再是一个,rename
而是应该是递归文件和目录删除。rename
不是设计来这样做的,所以它失败了,mv
不会进一步,因为它假设你不想这样做并且也失败了。
答案4
如果你想用另一个目录替换里面的内容,你可以使用
mv --backup=simple src dest
这会将 重命名dest
为dest~
并将 移动src
到dest
。