我有两个目录需要合并在一起。这两个目录中的文件都是大文件(>= 500MB)。
我想要存档的内容:对于源目录中的文件:如果它不存在于目标目录中,mv
则将其复制到目标目录(这很快,因为我们基本上是在创建一个新的硬链接并取消链接源文件);如果它存在于目标目录中,则将源文件复制到那里并删除源文件。
Linux 系统中最常见的目录合并方式是使用rsync
with--remove-source-files
选项,但这种方式比较慢,因为即使目标文件不存在也会进行复制操作。
还有更好的想法吗?谢谢。
答案1
基本上,您所描述的是将文件移动到覆盖目标(如果存在)。因此,只需移动它们即可。
答案2
有一种情况会mv
失败。以下是一些示例数据:
mkdir -p src/d dest/d
touch src/d/f1 dest/d/f2
看看如何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
因此创建一个脚本文件:
vim supermove
此示例不进行错误检查(免责声明:对我有用,但请测试它是否对您有用……也许使用echo
before mv
),并将覆盖具有相同路径的文件。它使用 find ,\;
效率极低,但+
无法正确使用"$dest"
前置。旧版本会创建一些没有前置路径的目录,而较新版本的 find 会说:
find: In '-exec ... {} +' the '{}' must appear by itself, but you specified 'dest/{}'
不过,您可能可以找到使用 xargs 修复该问题的方法。(我移动的 64k 文件 8TB 花了几分钟时间)。添加此内容:
#!/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"/
并使其可执行:
chmod +rx supermove
然后运行它
./supermove src/ dest/
结果...之前:
$ find src dest
src/
src/d
src/d/f1
dest/
dest/d
dest/d/f2
后:
$ find src dest
src
src/d
dest
dest/d
dest/d/f1
dest/d/f2
现在src/
应该只是空目录。如果是这样,您可以rm -r src
清理一下。
答案3
mv
选择都是为了解决冲突:
选一个:
-f force (always overwrite)
-i interactive (ask whether to overwrite)
-n no clobber (no overwrite)
这也很好:
-v verbose
否则,数据可能会丢失,或者不清楚到底发生了什么。
mv 在同一个文件系统上也更胜一筹,因为它只是更新目录 inode,文件不应该被弄乱。另一件事是,操作越大,出错的可能性就越大,比如软错误。