在Unix上recursion移动实用程序?

有时候我有两棵树曾经拥有相同的内容,但已经不同步了(因为我把磁盘移动了或者其​​它东西)。 一个很好的例子就是我从Fedora的上游软件包镜像。

我想通过将所有文件从tree1移动到tree2来再次合并这两个树。

通常我会这样做:

rsync -arv tree1/* tree2 

然后删除tree1。

但是,这需要花费大量的时间和磁盘空间,而且要做到这一点会容易得多:

 mv -r tree1/* tree2 

换句话说,recursion移动。 这会更快,因为首先它不会复制,只是移动inode,第二我不需要在最后删除。

这是否存在?

作为一个testing用例,请考虑以下一系列命令:

 $ mkdir -pa/b $ touch a/b/c1 $ rsync -arv a/ a2 sending incremental file list created directory ./ b/ b/c1 b/c2 sent 173 bytes received 57 bytes 460.00 bytes/sec total size is 0 speedup is 0.00 $ touch a/b/c2 

现在有什么命令将a / b / c2移动到a2 / b / c2,然后删除一个子树(因为其中的所有内容都已经在目标树中)?

根据gnu的mv的mv(1)手册页:

-u, --update move only when the SOURCE file is newer than the destination file or when the destination file is missing

build议mv -uf dir1/* dir2/移动(子)目录,而不是每个文件。 你可以尝试使用find

 cd dir1 find . -type d -exec mkdir -p dir2/"{}" \; find . -type f -exec mv -uf "{}" dir2/"{}" \; 

或类似的东西

才不是

 mv -uf tree1/* tree2/ 

工作?

午夜指挥官(MC)也是很好的这种东西。 使用CTRL-t标记文件,按F6,当它要求覆盖目标文件时,如果要覆盖较旧的文件,请select“更新”。

您可以使用“cp -l&rm”进行设备内移动:

 cp -alv --backup=numbered tree1/* tree2 && rm -rf tree1/ 
  • cp的使用硬链接,而不是复制(这也防止跨设备操作)
  • --backup=numbered用于备份目标目录中现有文件的cp --backup=numbered

请注意这两个问题:

  • 如果您意外地在跨设备目标上运行,请使用&&来防止删除未复制的数据。 (在corss-device情况下cp退出状态为“ 1 ”,至less对于GNU coreutils)
  • tree1以“ . ”开始的文件,如果有的tree1 ,你会丢失它们。

哈维尔的答案与查找效果很好,除了它不会删除原来的目录。 在结尾添加:

 rmdir $(find . -type d |grep -v ^\.$) 

 mv dir1/* dir2/ 

或干脆

 rsync -arv --remove-source-files tree1/* tree2 

应该足够了,当dir1有太多条目时,你可能会遇到麻烦。

 find sourcedir -maxdepth 1 -exec echo mv {} targetdir/ \; 

应该是一个不错的select

 find sourcedir -maxdepth 1 -print0 |xargs -0 -I _ echo mv _ targetdir find sourcedir -maxdepth1 -exec mv {} targetdir/ + 

都不是真的有必要,因为mv只需要2个选项(源目标),所以在这种情况下你将不得不忍受大量的进程。

 cd /tree1 mv * /tree2 

这不会移动隐藏的文件或文件夹,但您的原始示例不会。

我认为MV不会做你认为的事情。

一个unix文件系统有三个组件:

  • 目录条目
  • 索引节点

目录条目指向一个inode。

inode具有关于文件的元数据(是一个文件,一个目录,一个命名pipe道?谁拥有它?权限是什么?inode使用了哪些块?

块是实际包含文件内容的东西。

所以 – 当你“mv”一个文件时,你所要做的就是取消第一个目录项的链接,并把它重新链接到别的地方。

 snoopy -> inode 333 woodstock -> inode 333 

没有数据被复制/复制。 您创build链接监听,然后创build链接woodstock,然后删除链接监听。 (与目录有些不同,因为通常你不能制作硬链接的目录,但即使如此,“链接”的名称也会改变)。

如果你从一个文件系统移动到另一个文件系统呢? 在过去,mv只会抛出一个错误,并明确表示不能将文件从一个文件系统移动到另一个文件系统。 这些天,似乎mv默默复制数据,然后删除原来的。

在过去,由于无法将数据从一个文件系统移动到另一个文件系统,因此您习惯使用类似的习惯用法

tar -cf – 。 | (cd / new / location && tar -xf – )

那么你删除了旧的数据。 使用tar的部分原因是,在过去,cp会破坏元数据,如“这是一个符号链接”和“这是一个硬链接”,而只是获取该文件的新副本作为常规文件。 即使如此,你仍然需要给“cp”标志来告诉它保存这种结构。

如果从一个文件系统到另一个文件系统,则无法避免“移动”大量数据。 不要紧,如果你使用奇特的新移动或rsync或焦油或cpio。

但是,如果将所有数据保存在同一个文件系统中,则:

mv / filesystem-1 / big / directory * / filesystem-1 / big2 /

这将是非常快的,因为它只是改变目录条目,而不是实际移动任何实际的数据。

还有其他的问题,例如,如果新位置已经有一个文件/目录以及源位置,你应该怎么做?

切换到你想要移动的目录

 tar cf - * | ( cd /target; tar xfp -) 

比mv快…