在 Linux 中合并同一文件系统上的两个目录的最佳方法是什么?

yeg*_*gle 5 linux

我有两个目录需要合并在一起。这两个目录下的文件都是大文件(>=500MB)。

我想要归档的内容: 对于源目录中的文件:如果目标目录中不存在,则将其归档mv到目标目录(这很快,因为我们基本上是创建一个新的硬链接并取消链接源文件);如果目标目录中存在,则将源文件复制到那里并删除源文件。

Linux系统中合并目录最常用的方法是使用rsyncwith--remove-source-files选项。但这很慢,因为即使目标文件不存在,它也会执行复制操作。

还有更好的想法吗?谢谢。

Pet*_*ter 7

有一个mv失败的案例。以下是一些示例数据:

mkdir -p src/d dest/d
touch src/d/f1 dest/d/f2
Run Code Online (Sandbox Code Playgroud)

看看如何mv失败:

$ mv src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -f src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fv src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fvi src/* dest/
mv: overwrite 'dest/d'? y
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fvi -t dest/ src/*      
mv: overwrite 'dest/d'? y
mv: cannot move 'src/d' to 'dest/d': Directory not empty
Run Code Online (Sandbox Code Playgroud)

所以制作一个脚本文件:

vim supermove
Run Code Online (Sandbox Code Playgroud)

此示例不进行错误检查(免责声明:对我有用,但请测试它是否对您有用...也许与echobefore一起mv使用),并将覆盖具有相同路径的文件。它使用 find ,\;效率非常低,但+不能与"$dest"prepending 一起正常工作。旧版本会创建一些没有前缀路径的目录,而新版本的 find 会说:

find: In '-exec ... {} +' the '{}' must appear by itself, but you specified 'dest/{}'
Run Code Online (Sandbox Code Playgroud)

不过,您也许可以找到一种使用 xargs 来解决该问题的方法。(我移动 8TB 的 64k 文件花了几分钟)。添加此内容:

#!/bin/bash

src=$1
dest=$2

src=$(readlink -f "$src")
dest=$(readlink -f "$dest")

cd "$src"

# also copy hidden files
shopt -s dotglob

# make dirs (missing old permission,acl,xattr data), and then mv the files
time find * -type d -exec mkdir -p "$dest"/{} \;
time find * -type f -exec mv {} "$dest"/{} \;

# also copy permissions, acls, xattrs
rsync -aAX "$src"/ "$dest"/
Run Code Online (Sandbox Code Playgroud)

并使其可执行:

chmod +rx supermove
Run Code Online (Sandbox Code Playgroud)

并运行它

./supermove src/ dest/
Run Code Online (Sandbox Code Playgroud)

结果......之前:

$ find src dest
src/
src/d
src/d/f1
dest/
dest/d
dest/d/f2
Run Code Online (Sandbox Code Playgroud)

后:

$ find src dest
src
src/d
dest
dest/d
dest/d/f1
dest/d/f2
Run Code Online (Sandbox Code Playgroud)

现在src/应该只是空目录。如果是这样,您可以rm -r src进行清理。

  • 我喜欢这个剧本。正是我正在寻找的东西。不再需要使用“rsync”合并同一分区上的目录来磨损硬盘。我使用“tree”来检查空目录树(以防万一),但如果出现问题(缺少权限、覆盖文件等),命令会打印错误。感谢您的“dotglob”选项! (2认同)

Bar*_*cki 4

基本上,您所描述的是将文件移动到覆盖目的地(如果存在)。所以只要移动它们即可。

  • 我太沉迷于合并目录的想法,并且没有意识到“mv”可以完成这项工作。感谢您和@Michael Hampton 指出这一点。 (2认同)