81

On the diff man-page I've found these exit values:

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

Are there different exit values above 1 for different errors?

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
sid_com
  • 24,137
  • 26
  • 96
  • 187
  • 2
    On macOS, the diff man page leaves output values undefined – William Entriken Oct 23 '18 at 01:32
  • I wish there were, and I wish they were documented, because a missing file is a particular case: it can be seen as an error, when comparing one pair of files, but it can be seen as a difference, when comparing _collections of files_, such as e.g. a recursive `diff` run, between 2 folders. – JMB Oct 12 '21 at 07:39
  • @WilliamEntriken The man page on macOS explicitly states to consult `info diff` for the complete manual. There, under `Invoking diff`, it states "An exit status of 0 means no differences were found, 1 means some differences were found, and 2 means trouble." – Colin 't Hart Feb 23 '23 at 08:30

4 Answers4

85

It depends on your diff command. Mine (GNU diffutils 3.0) says:

An exit status of 0 means no differences were found, 1 means some differences were found, and 2 means trouble. Normally, differing binary files count as trouble, but this can be altered by using the -a or --text option, or the -q or --brief option.

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • 4
    agreed, I checked the sources, and the only exit codes are EXIT_SUCCESS, EXIT_FAILURE (both defined in stdlib.h) and EXIT_TROUBLE, defined in src/diffutils-3.0/system.h – jcomeau_ictx Aug 07 '11 at 07:26
  • The '--text' option makes a mess of my STDOUT if there are two (big) different binary files. – sid_com Aug 07 '11 at 08:16
  • @sid_com, when your standard output is messed up, try blind-typing `echo^V^[c` (`echo-[control-v]-[escape]-c`) or `stty sane` in your terminal. – Frédéric Hamidi Aug 07 '11 at 08:20
  • @Frédéric Hamidi: messed up in the sense that I have to scroll a lot (when using `diff -r`). – sid_com Aug 07 '11 at 08:27
  • Edit: I'm using `diff` with perls `IPC::System::Simple::system` which lets me specify a range of values which are considered acceptable exit values. – sid_com Mar 16 '13 at 06:06
  • FYI the man page, `man diff`, for the older diff versions < 3.0 do not provide any documentation on what the "exit values" (aka "exit status", "return values") are. The man page on newer versions 3.0+ of diff do provide documentation on the "exit value" (the bit about the "Exit status" is IMO a little hard to find because it is near the bottom of the man page... at the bottom of the section that describes all the options). – Trevor Boyd Smith Dec 16 '15 at 18:37
11

There maybe, or there may not be different error codes depending upon the version of diff you use. If I remember correctly, the standard BSD diff always returned an exit code of 0, 1, or 2.

However, the manpage isn't mapping out everything that diff might do, but the documentation you can use for using diff command. In a shell script, I want to know if the files matched (exit = 0) or didn't match (exit = 1). However, in my shell script, I also want to know that the diff command itself didn't work.

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

Imagine if I was told that 2 meant the diff command failed, but a newer version of the diff command made a distinction between a file you can't read (exit = 2) and a missing file (exit = 3). Now, imagine if I did the following in an earlier version of the diff command, but $file2 didn't exist:

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

In the above code, I checked for the error code of 2 and 1, but not 3. So, instead of detecting a missing file, I assume that the files match.

The manpage is trying to make sure that future upgrades to the OS don't cause most of your shell scripts to suddenly fail. It's why there was a separate awk and nawk command and a separate grep and egrep command.

*Updated as per comment by @chus.

M Somerville
  • 4,499
  • 30
  • 38
David W.
  • 105,218
  • 39
  • 216
  • 337
  • 3
    Be careful: `$?`is updated after executing `if [ $? eq 0 ]`, so the `elif` evaluation is not related to the diff output. – chus Dec 01 '15 at 09:10
  • 1
    "There [may or may] not be different error codes depending upon the version of `diff` you use." [POSIX `diff` exits with 0 when files are identical, 1 when they differ, and >1 otherwise](http://pubs.opengroup.org/onlinepubs/009696799/utilities/diff.html). So you can't assume 2, but 0 and 1 are safe. – David Ehrmann Oct 06 '16 at 04:00
  • @DavidEhrmann In the BSD version of the `diff` command the Mac used when this answer was written, the diff manpage listed the error codes as 0, 1, or 2. The Mac now uses diffutils from GNU, so the error codes in the manpage are now 0, 1, and >1. All Unix`diff` commands say that `0` means the files matched and 1 means differences were found. After that, the documentation differs. – David W. Oct 06 '16 at 14:40
  • Unrelated to the topic of diff return values, but there should be a "then" after the "elif" line – L. Scott Johnson Nov 16 '17 at 19:05
  • IMHO, a better solution to the problem pointed out by @chus would be using a `case` instead of `if+elif...`. Then you evaluate `$?` only once. – JMB Oct 12 '21 at 07:32
3

In my case diff returned 127. Searched for it and found it in the tldp.org "Exit Codes With Special Meanings"

127 "command not found" - illegal_command - Possible problem with $PATH or a typo.

I used an incorrect path to diff. :)

Font: Advanced Bash-Scripting Guide.

Don't Panic
  • 13,965
  • 5
  • 32
  • 51
Rossano Fenner
  • 135
  • 1
  • 7
0

macOS uses similar return codes to GNU diff but explicitly defines 2 as the return code for an error situation:

An exit status of 0 means no differences were found, 1 means some differences were found, and 2 means trouble.

-- from info diff, section "Invoking diff", under macOS 12.6.3

Colin 't Hart
  • 7,372
  • 3
  • 28
  • 51