为什么 mv 比 cp 快这么多?如何从不正确的 mv 命令中恢复?

AGa*_*yer 21 cp file-copy mv

我在 FileZilla 中错误地将一个文件夹拖放到另一个文件夹中。

~/big_folder
~/some_other_folder
Run Code Online (Sandbox Code Playgroud)

移动的文件夹是一个非常大的文件夹。它包括数十万个文件(node_modules,小图像文件,很多文件夹)

奇怪的是,当我松开鼠标后,移动就完成了。文件夹“big_folder”被移动到“some_other_folder”中。

~/some_other_folder/big_folder
Run Code Online (Sandbox Code Playgroud)

(没有big_folder~/移动之后)

然后我意识到错误并尝试返回,但它在 FileZilla 和终端上都失败了。

然后我必须cp -r将文件复制回来,因为有服务器端代码访问这些文件~/big_folder

而且需要永远等待......

我该怎么办?

顺便说一句,这里是 FileZilla 的输出(这是搬回的失败):

Status:       Renaming '/root/big_folder' to '/root/some_other_folder/big_folder'
Status:       /root/big_folder -> /root/some_other_folder/big_folder

Status:       Renaming '/root/some_other_folder/big_folder' to '/root/big_folder'
Command:  mv "big_folder" "/root/big_folder"
Error:          mv /root/some_other_folder/big_folder /root/big_folder: received failure with description 'Failure'
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 70

如果一个目录被移动相同的文件系统(在同一个分区)内,则所有需要的是重命名的目录的文件路径。除了目录本身的目录条目之外,无需更改任何数据。

复制目录,被复制的每个数据,每个文件的需求。这涉及读取所有源数据并将其写入目标。

文件系统之间移动目录将涉及将数据复制到目标并将其从源中删除。这将花费与在单个文件系统中复制(复制)数据一样长的时间。


如果 FileZilla 成功地将目录从~/big_folderto重命名~/some_other_folder/big_folder,那么我将使用

mv ~/some_other_folder/big_folder ~/big_folder
Run Code Online (Sandbox Code Playgroud)

...首先确保没有所谓的目录之后~/big_folder(如果有,此举将使big_foldersome_other_folder进入~/big_folder目录的子文件夹)。

  • 另一个不依赖 Windows GUI 工具在 Unix 上进行文件维护的原因。 (10认同)
  • 哦......这就是为什么我在输出中看到“重命名”而不是“移动”这个词的原因? (7认同)
  • 不幸的是,@AGamePlayer "Failure" 不是一个好的错误描述。在确保主目录中没有其他 `big_folder` 之后,我会使用 `mv ~/some_other_folder/big_folder ~/`。我从未使用过 FileZilla。 (4认同)
  • @MarkStewart 为什么在您的评论末尾“在 Unix 上”?;有没有什么时候这是一个好主意? (4认同)
  • @AGamePlayer 是的,正确。 (2认同)

for*_*est 12

现有的答案很好,但我想通过准确显示移动时与复制文件时发生的情况来稍微扩展一下。当您在复制期间查看系统调用时,您会看到:

open("hello1.txt", O_RDONLY)               = 3
open("hello2.txt", O_WRONLY|O_CREAT, 0644) = 4
read(3, "Hello, world!\n", 4096)           = 14
write(4, "Hello, world!\n", 14)            = 14
close(3)                                   = 0
close(4)                                   = 0
Run Code Online (Sandbox Code Playgroud)

这将打开源文件,然后创建第二个文件。然后它将源文件的内容读取到内存并将该内存写入目标文件。这需要多个上下文切换和一些磁盘 I/O,这对于大文件来说可能相当高。但是,如果您移动文件,则会看到:

rename("hello1.txt", "hello2.txt")         = 0
Run Code Online (Sandbox Code Playgroud)

重要的是要记住,只有在同一物理磁盘上的同一文件系统上,您才会看到文件被重命名。如果您创建了一个巨大的、数 GB 的文件,然后在您家中的两个位置之间移动它,您会发现操作立即完成。另一方面,如果您将其移动到外部设备,则移动所需的时间与您使用的时间一样长cp。系统调用跟踪将与第一个相同,但unlink("hello1.txt")在最后。这是因为如果源和目标位于同一文件系统上,则只能使用重命名来移动文件。

  • @AL 在类 Unix 系统中,一切都是文件。 (2认同)