在 Linux 中合并 2 个目录树而无需复制?

在 Linux 中合并 2 个目录树而无需复制?

我有两个布局相似的目录树,即

.
 |-- 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

相关内容