递归比较两个带有diff -r的目录,而不在断开的链接上输出


38

diff -r a b用来递归比较目录ab。尽管经常有一些断开的链接(ab目录中相同的断开链接并指向相同的,不存在的目标),但这种情况经常发生。

diff然后针对这些情况输出错误消息,并以非零退出代码退出,但是我希望它保持沉默,并以0退出,因为目录与我的书相同。

我怎样才能做到这一点?


您是否仍要比较符号链接(并标识为等效但已损坏),或者在进行此差异时忽略所有符号链接是否可以接受?
ire_and_curses 2012年

比较并确定为等效,我不在乎它们是否损坏。我只是想验证我的rsync是否正常工作。
马库斯·朱尼乌斯·布鲁图斯

Answers:


24

对于3.3版或更高版本diff,您应该使用该--no-dereference选项,如Pete Harlan的答案中所述

不幸的是,旧版本的diff 不支持忽略符号链接

有些文件既不是目录也不是常规文件:它们是不寻常的文件,例如符号链接,设备专用文件,命名管道和套接字。目前,diff将符号链接视为常规文件;如果在顶层指定了特殊文件,它将像普通文件一样对待其他特殊文件,但是在比较目录时只报告它们的存在。这意味着patch不能代表对此类文件的更改。例如,如果更改符号链接指向的文件,则diff输出两个文件之间的差异,而不是更改符号链接。

diff应该有选择地专门报告对特殊文件的更改,并且patch应该扩展以了解这些扩展名。

如果您只想验证rsync(并大概修复所缺少的内容),则可以再次运行rsync命令。如果您不想这样做,那么检查目录总和就足够了。

如果您确实想使用来执行此操作diff,则可以使用find跳过符号链接,并分别对每个文件运行diff。将目录ab作为参数传递:

#!/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中b中没有的文件。

注意:

  • 因为我们完全跳过了符号链接,所以如果b中不存在符号链接名称,这将不会引起注意。如果需要,则需要第二次查找通过以识别所有符号链接,然后在b中显式检查它们的存在。
  • 由于列表是根据a的内容构造的,因此不会识别b中的多余文件。对于您的方案,这可能不是问题。rsync

建议的脚本不适用于目录'a'中存在的任何目录(使用b / $ {f ## *}为'b'创建的路径不正确)。
Marcus Junius Brutus 2014年

@MarcusJuniusBrutus-是的,您是对的。我认为解决方案是删除#,例如,for f in 找到a / *!类型l ;do echo $f b/${f#*/};done。我现在没有时间对此进行测试。让我知道是否可行。
ire_and_curses 2014年

比较好,然而它仍然在许多情况下,搅乱文件路径。该脚本(删除了#的脚本)似乎需要直接在“ a”上的目录中调用才能正常工作。
Marcus Junius Brutus 2014年

使用GNU diff 3.3时,此答案已过时(请参阅下面的帖子)
Bernd Gloss

上面的脚本有几个问题,这是由于首先找到所有文件名并将它们提供给扩展的命令行。(1)自此以来,它仅适用于少量文件集合。(2)任何带有特殊字符(甚至空格)的文件名都不会被处理。(3)始终使用$(xxx)反引号代替。反引号的对称性使它们的可读性降低,并防止嵌套。关于图1和2见stackoverflow.com/questions/11366184/...
斯特凡纳·古里科

19

从3.3版开始,GNU diff不支持取消引用符号链接,而是比较它们指向的路径。

安装GNU diffutils> = 3.3并使用该--no-dereference选项;没有简短的选择。

如果等于或以下,则诊断将保持静音:

符号链接/tmp/noderef/a/symlink/tmp/noderef/b/symlink不同


现在,如果它将显示内容更改,就好像符号链接是常规文件...:-/
lindes

6

您可以使用更高版本的 diff

diff在GNU diffutils3.3包括一个--no-dereference选项,允许您将符号链接本身比较,而不是他们的目标。它报告他们是否不同,如果他们同意则保持安静,并且不在乎是否被破坏。

我不知道该选项何时添加;它在2.8.1中不存在。


我可以确认diff(GNU diffutils)3.2中也不存在
Elder Geek
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.