考虑以下目录/文件结构(所有叶节点都是常规文件,但这并不重要):
$ tree
.
├── cool_1
│ ├── dumb
│ │ ├── file1
│ │ └── file2
│ └── foo
│ └── dumb
└── cool_2
├── dumb
│ ├── file1
│ └── file2
└── foo
└── dumb
我想对两个目录进行递归比较,但不包括常规文件 <root>/foo/dumb
但不是全部目录 <root>/dumb
。
我查看了--exclude
,--exclude-from
如果man 1 diff
有办法创建一个模式来实现这一点,我感到很困惑,除了编写一个手动执行递归的脚本或类似的东西。我如何比较目录并排除我想要的和仅排除我想要的?
答案1
我假设您想要diff -r cool_1 cool_2
排除。
--exclude
并且--exclude-from
确实太有限。
有一种方法,虽然有点麻烦,但其核心却非常简单:
将您想要的两个目录复制
diff
到其他地方。例如,让目标目录为target/
。然后我们的基本命令是cp -R cool_1 cool_2 target/
。笔记:
您
target/
不希望预先包含cool_1
或cool_2
。一个好主意是创建一个新的空目录 (mkdir target
),然后cp
进入该目录。您想要
-P
(将符号链接复制为符号链接)。cool_1
理想情况下,和中的整个目录层次结构cool_2
都属于单个文件系统。如果是这样,请选择同一文件系统内的目标目录,然后:- 使用
cp -l
并创建到常规文件的硬链接,而不是实际复制它们(尽管您cp
可能支持也可能不支持-l
); cp --reflink=always
或者,如果文件系统支持 reflinks 并且您的cp
支持,则使用创建 reflinks--reflink
。如果没有充分的理由使用 reflinks,则应使用硬链接。使用 reflinks 的充分理由是,当cool_1
或下面的某些常规文件cool_2
是不可变的,并且您无法为其创建新的硬链接时。
这样,您将避免不必要的实际复制。这不仅与 I/O 有关,硬链接或重新链接消耗的额外磁盘空间也比实际复制少得多。
- 使用
该命令如下:
cp -RPl cool_1 cool_2 target/
进入目标目录:
cd target/
确保没有错误并且您位于目标目录中。
用任何手段来真正消除您想要排除的文件。使用
rm
、 或 中手动删除它们mc
,或使用一些自动化方法。例如此命令:find cool_1 cool_2 -name dumb ! -type d -delete
将删除目录类型文件之外的所有文件
cool_1
或cool_2
以基本名称命名的文件。不可移植,如有必要,请使用;参见dumb
-delete
-exec rm {} \;
这个问题。如果目标目录(现在是我们的.
)仅包含cool_1
,cool_2
那么您可以简化并对整个目录采取行动:find . …
你可能会发现这个问题很有用:递归搜索具有排除和包含的文件。
用于
tree
检查层次结构是否良好。您还可以运行类似diff -r cool_1 ../cool_1
和diff -r cool_2 ../cool_2
查看已删除的内容。如果删除的内容过多,请记住,您可以随时从原始目录再次复制(硬链接、重新链接)。由于您甚至可以逐个删除(或重新添加)文件,因此可以实现任意排除。
diff -r
在目标目录内使用:diff -r cool_1 cool_2
这里
cool_1/
不cool_2/
包含您想要排除的文件,因此无需告知diff
排除任何内容。最终删除目标目录:
cd .. && rm -r target/