我有一个文件夹的两个副本
src/
dest/
我想合并它们,执行以下操作:
如果文件仅在src
,我希望将其移动到dest
如果某个文件仅在中dest
,我希望 IE 忽略它。
如果文件同时在和具有相同的内容(即相同的大小和日期),从中删除src
如果文件同时在并且不是具有相同的内容,保留下来,src
以便我可以手动合并它们。
只有极少数文件(占总文件的 0%到 5% 之间)应该属于最后一个类别,但我不知道如何区分两者中的和两者中的相同但不同的。
我曾尝试弄清楚如何做到这一点,rsync
但至今无果。
答案1
我只进行了有限的功能测试,因此请小心使用此命令(--dry-run):
rsync -avPr --ignore-existing --remove-source-files src/ dest
请注意尾随的 /,因为这将递归到 src 而不是复制 src 本身,这应该保留您现有的路径。
通过将 --ignore-existing 标志与 --remove-source-files 标志结合使用,您将仅删除从 src 同步到 dest 的 src 文件,即以前不存在于 dest 中的文件。
要删除未同步的文件(即 dest/ 中已经存在的文件,如 src/ 中的文件),您可以使用:
for file in `find src/ -type f`; do diff $file `echo $file | sed 's/src/dest/'` && rm $file || echo $file; done
或者
find src -type f -exec bash -c 'cmp -s "$0" "${0/#src/dest}" && rm "$0"' {} \;
如果文件名可以包含空格/换行符/… 关于 Gilles 关于特殊字符的评论,这当然是需要注意的,而且有很多解决方案,最简单的方法是将 -i 传递给 rm,它将在删除所有文件之前提示。但是,如果提供了 src/ 或其父路径以供 find,则完全限定路径应该会导致 diff 和 rm 命令正确处理所有文件名,而无需引用。
答案2
齐奏就是您要找的工具。如果您更喜欢 gui,请尝试 unison-gtk。但我认为它不会删除类似的文件:unison 尝试让两个目录相同。尽管如此,它还是可以轻松 1) 识别要复制哪些文件;2) 哪些文件需要手动合并。
答案3
以下脚本应该可以合理地执行操作。它将文件从源移动到目标,从不覆盖文件并根据需要创建目录。在目标中具有相应不同文件的源文件将保持不变,非常规文件或目录(例如符号链接)的文件也是如此。源中剩余的文件是存在冲突的文件。请注意,我根本没有测试过它。
cd src
find . -exec sh -c '
set -- "/path/to/dest/$0"
if [ -d "$0" ]; then # the source is a directory
if ! [ -e "$1" ]; then
mv -- "$0" "$1" # move whole directory in one go
fi
elif ! [ -e "$0" ]; then # the source doesn't exist after all
: # might happen if a whole directory was moved
elif ! [ -e "$1" ]; then # the destination doesn't exist
mv -- "$0" "$1"
elif [ -f "$1" ] && cmp -s -- "$0" "$1"; then # identical files
rm -- "$0"
fi
' {} \;
另一种方法是联合山一个目录在另一个目录之上,例如函数或者unionfs-fuse。