我有两个布局相似的目录树,即
.
|-- dir1
| |-- a
| | |-- file1.txt
| | `-- file2.txt
| |-- b
| | `-- file3.txt
| `-- c
| `-- file4.txt
`-- dir2
|-- a
| |-- file5.txt
| `-- file6.txt
|-- b
| |-- file7.txt
| `-- file8.txt
`-- c
|-- file10.txt
`-- file9.txt
我想合并 dir1 和 dir2 目录树来创建:
merged/
|-- a
| |-- file1.txt
| |-- file2.txt
| |-- file5.txt
| `-- file6.txt
|-- b
| |-- file3.txt
| |-- file7.txt
| `-- file8.txt
`-- c
|-- file10.txt
|-- file4.txt
`-- file9.txt
我知道我可以使用“cp”命令来执行此操作,但我想移动文件而不是复制,因为我要合并的实际目录非常大,包含大量文件(数百万个)。如果我使用“mv”,我会因为目录名称冲突而收到“文件存在”错误。
更新:您可以假设两个目录树之间没有重复的文件。
答案1
rsync -ax --link-dest=dir1/ dir1/ merged/
rsync -ax --link-dest=dir2/ dir2/ merged/
这将创建硬链接而不是移动它们,您可以验证它们是否被正确移动,然后dir1/
删除dir2/
。
答案2
奇怪的是没有人注意到cp
有选项-l
:
-l,--link 硬链接文件而不是复制
你可以做类似的事情
%mkdir合并 %cp -rl dir1 / * dir2 / *合并 %rm -r 目录* % 树合并 合并 ─ 一 │ │ ── 文件1.txt │ │ ── 文件2.txt │ │ ── 文件5.txt │ └── 文件6.txt │ │ │ │ ── 文件3.txt │ │ ── 文件7.txt │ └── file8.txt └── c ═── 文件10.txt │ │ 文件4.txt └── file9.txt 13 个目录,0 个文件
答案3
您可以使用 rename(又名 prename,来自 perl 包)来实现这一点。请注意,名称不一定指我在 debian/ubuntu 之外描述的命令(尽管如果您需要它,它是一个单独的可移植 perl 文件)。
mv -T dir1 merged
rename 's:^dir2/:merged/:' dir2/* dir2/*/*
find dir2 -maxdepth 1 -type d -empty -delete
您还可以选择使用 vidir(来自 moreutils),并使用您喜欢的文本编辑器编辑文件路径。
答案4
暴力破解bash
#! /bin/bash
for f in $(find dir2 -type f)
do
old=$(dirname $f)
new=dir1${old##dir2}
[ -e $new ] || mkdir $new
mv $f $new
done
测试这样做
# setup
for d in dir1/{a,b,c} dir2/{a,b,c,d} ; do mkdir -p $d ;done
touch dir1/a/file{1,2} dir1/b/file{3,4} dir2/a/file{5,6} dir2/b/file{7,8} dir2/c/file{9,10} dir2/d/file11
# do it and look
$ find dir{1,2} -type f
dir1/a/file1
dir1/a/file2
dir1/a/file5
dir1/a/file6
dir1/b/file3
dir1/b/file7
dir1/b/file8
dir1/c/file4
dir1/c/file9
dir1/c/file10
dir1/d/file11