![使用 diff -r 递归比较两个目录,而不在损坏的链接上输出](https://linux22.com/image/25964/%E4%BD%BF%E7%94%A8%20diff%20-r%20%E9%80%92%E5%BD%92%E6%AF%94%E8%BE%83%E4%B8%A4%E4%B8%AA%E7%9B%AE%E5%BD%95%EF%BC%8C%E8%80%8C%E4%B8%8D%E5%9C%A8%E6%8D%9F%E5%9D%8F%E7%9A%84%E9%93%BE%E6%8E%A5%E4%B8%8A%E8%BE%93%E5%87%BA.png)
我在用diff -r a b
递归比较目录A和乙。尽管存在一些损坏的链接(两个中的相同损坏链接),但经常会发生这种情况A和乙目录并指向相同的、不存在的目标)。
差异然后输出这些情况的错误消息并以非零退出代码退出,但是我希望它保持沉默,并以 0 退出,因为目录在我的书中是相同的。
我怎样才能做到这一点?
答案1
对于 3.3 或更高版本diff
,您应该使用该--no-dereference
选项,如中所述皮特·哈伦的回答。
不幸的是,旧版本diff
不支持忽略符号链接:
有些文件既不是目录也不是常规文件:它们是不寻常的文件,例如符号链接、设备特殊文件、命名管道和套接字。目前,
diff
将符号链接视为常规文件;如果在顶层指定了其他特殊文件,它会将它们视为常规文件,但在比较目录时仅报告它们的存在。这意味着patch
不能代表对此类文件的更改。例如,如果更改符号链接指向的文件,diff
则输出两个文件之间的差异,而不是对符号链接的更改。
diff
应该选择专门报告对特殊文件的更改,并且patch
应该进行扩展以了解这些扩展。
如果您想要的只是验证 rsync(并且可能修复丢失的内容),那么您可以再次运行 rsync 命令。如果你不想这样做,那么对目录进行校验和可能就足够了。
如果您确实想使用 执行此操作diff
,则可以使用find
跳过符号链接,并对每个文件单独运行 diff。传递你的目录A和乙作为参数:
#!/bin/bash
# Skip files in $1 which are symlinks
for f in `find $1/* ! -type l`
do
# Suppress details of differences
diff -rq $f $2/${f##*/}
done
或作为单行:
for f in `find a/* ! -type l`;do diff -rq $f b/${f##*/};done
这将识别内容不同的文件,或A但不在乙。
注意:
- 由于我们完全跳过符号链接,因此不会注意到符号链接名称是否不存在于乙。如果您需要这样做,则需要第二次查找过程来识别所有符号链接,然后显式检查它们是否存在于乙。
- 额外文件位于乙不会被识别,因为该列表是根据以下内容构建的A。对于您的场景来说,这可能不是问题
rsync
。
答案2
从版本 3.3 开始,GNUdiff
支持不取消引用符号链接,而是比较它们指向的路径。
安装 GNU diffutils
>= 3.3 并使用该--no-dereference
选项;对此没有简短的选择。
如果等于或以下情况,诊断将保持沉默:
符号链接/tmp/noderef/a/symlink
和/tmp/noderef/b/symlink
不同
答案3
您可以使用较新版本的diff
diff
GNU diffutils
3.3 中包含一个选项--no-dereference
,允许您比较符号链接本身而不是它们的目标。如果它们不同,它会报告;如果它们同意,它会保持安静,并且不关心它们是否被破坏。
我不知道这个选项是什么时候添加的;它在 2.8.1 中不存在。
答案4
此代码比较两个文件夹中的文件,但使用第一个文件夹的文件名作为基线
diffDir() {
A=$1
B=$2
for src in `find $A ! -type l` ; do
dst=/data/f-stack/freebsd/${src#$A}
if [ -f $dst ]; then
GIT_PAGER= git diff --no-ext-diff $src $dst;
fi
done
}
diffDir /data/freebsd/freebsd11.0/sys/ /data/f-stack/freebsd/