diff 的错误退出值是什么?

82

我在 diff man-page 中找到了以下退出值:

    0     No differences were found. 
    1     Differences were found.
   >1     An error occurred.

不同的错误会产生大于 1 的不同退出值吗?


2
在macOS上,diff man页面未定义输出值。 - William Entriken
我希望有这样的文档,因为缺少文件是一个特殊情况:当比较一对文件时,它可以被视为错误,但当比较文件集合(例如,在两个文件夹之间进行递归diff运行)时,它可以被视为差异。 - JMB
@WilliamEntriken 在 macOS 上的 man 页面明确指出要查阅 info diff 获取完整手册。在那里,Invoking diff 下面写着:“退出状态为 0 表示没有发现差异,1 表示发现了一些差异,2 表示有问题。” - Colin 't Hart
4个回答

86
这取决于您使用的 diff 命令。我的(GNU diffutils 3.0)显示:
一个退出状态为 0 表示没有发现差异, 1 表示发现了一些差异, 2 表示出现问题。通常,不同的二进制文件被视为问题,但可以通过使用 -a 或 --text 选项或 -q 或 --brief 选项来更改此设置。

4
同意,我查阅了资料,发现唯一的退出码是EXIT_SUCCESS(成功退出)和EXIT_FAILURE(失败退出),它们都在stdlib.h中定义。而EXIT_TROUBLE则在src/diffutils-3.0/system.h中定义。 - jcomeau_ictx
如果有两个(大)不同的二进制文件,则“--text”选项会使我的STDOUT混乱。 - sid_com
@sid_com,当你的标准输出出现问题时,请尝试在终端中盲打 echo^V^[c (echo-[control-v]-[escape]-c) 或 stty sane - Frédéric Hamidi
@Frédéric Hamidi:混乱的意思是我必须经常滚动页面(使用diff -r时)。 - sid_com
我正在使用diff和Perl的IPC::System::Simple::system,它允许我指定一系列被视为可接受的退出值。 - sid_com
FYI,旧版本 diff(<3.0)的 man 页面没有提供任何关于“退出值”(又称“退出状态”,“返回值”)的文档。新版本 3.0+ 的 diff 的 man 页面提供了有关“退出值”的文档(关于“退出状态”的部分在 man 页面底部附近,因为它在描述所有选项的部分的底部)。 - Trevor Boyd Smith

12

根据您使用的diff版本,可能会存在不同的错误代码,也可能没有错误代码。如果我没记错的话,标准的BSD diff命令返回0、1或2的退出代码。

然而,手册并未列出diff可能执行的所有操作,但您可以使用它来进行diff命令的文档说明。在shell脚本中,我想知道文件是否匹配(退出码=0)或不匹配(退出码=1),但是在我的shell脚本中,我还想知道diff命令本身是否工作正常。

diff $file1 file2 > /dev/null 2>&1
error=$?
if [ $error -eq 0 ]
then
   echo "$file1 and $file2 are the same file"
elif [ $error -eq 1 ]
then
   echo "$file1 and $file2 differ"
else
   echo "There was something wrong with the diff command"
fi

想象一下,如果我被告知2代表diff命令失败,但是较新版本的diff命令区分了您无法读取的文件(退出= 2)和丢失的文件(退出= 3)。现在,请想象一下,在较早版本的diff命令中我执行了以下操作,但是$file2不存在:

diff $file1 file2 > /dev/null 2>&1
error=$?
if [ $error -eq 2 ]
then
   echo "There was something wrong with the diff command"
elif [ $error -eq 1 ]
then
   echo "$file1 and $file2 differ"
else
   echo "$file1 and $file2 are the same file"
fi
在上面的代码中,我检查了错误代码2和1,但没有检查3。因此,我假设文件匹配而不是检测缺失的文件。
man页面试图确保操作系统的未来升级不会导致大多数shell脚本突然失败。这就是为什么有单独的awk和nawk命令以及单独的grep和egrep命令。
*按照@chus的评论进行更新。

3
иҜ·жіЁж„ҸпјҡеңЁжү§иЎҢ if [ $? eq 0 ] еҗҺ $? зҡ„еҖјдјҡиў«жӣҙж–°пјҢеӣ жӯӨ elif зҡ„иҜ„дј°дёҺ diff иҫ“еҮәж— е…ігҖӮ - chus
1
根据您使用的 diff 版本,可能会有不同的错误代码。POSIX diff 在文件相同时退出状态码为0,在文件不同时为1,在其他情况下为>1。因此,您不能假设为2,但0和1是安全的。 - David Ehrmann
@DavidEhrmann 在撰写本答案时,Mac 使用的 diff 命令的 BSD 版本中,diff manpage 将错误代码列为 0、1 或 2。现在 Mac 使用来自 GNU 的 diffutils,因此 manpage 中的错误代码现在为 0、1 和 >1。所有 Unix diff 命令都表示 0 表示文件匹配,而 1 表示发现了差异。之后,文档有所不同。 - David W.
与返回值差异主题无关,但在“elif”行后应该有一个“then”。 - L. Scott Johnson
在我看来,解决@chus指出的问题的更好方法是使用case而不是if+elif...。然后您只需要评估$?一次。 - JMB

3
在我的情况下,diff 返回了 127。查找并在 tldp.org 的 "Exit Codes With Special Meanings" 中找到了它。

127 “command not found” - illegal_command - 可能是$PATH的问题或者拼写错误。

我使用了一个不正确的路径来调用diff。 :)
来源: 高级Bash脚本指南

1
这不是diff返回127,而是因为您的shell无法执行diff而返回了127。 - Colin 't Hart
感谢 @Colin'tHart 的纠正! - Rossano Fenner

0

macOS使用类似于GNU diff的返回代码,但明确将2定义为错误情况的返回代码:

退出状态码为0表示没有发现差异,1表示发现了一些差异,2表示出现问题。

-- 来自于info diff,macOS 12.6.3下的"调用diff"部分


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接