Make assumes that an exit code of 0 means success, anything else means failure. This is the standard convention used by almost all command-line tools.
Unfortunately, diff
is not one of those. Checking the GNU diff info page, and also the Single Unix Specification "diff" entry, 0 means no differences found, 1 means differences found, and ≥2 means error.
You can tell Make to ignore the exit status entirely by prefixing the command with a hyphen, as you did in your comment, but this will ignore actual errors—probably not what you want. Instead, you can:
patch:
diff -u b a > b2a.patch; [ $$? -eq 1 ]
patch -o b.corrected b < b2a.patch
diff a b.corrected; [ $$? -eq 1 ]
Note the ; [ $$? -eq 1 ]
bit I've added to the end of the two diff lines. You can use ; test $$? -eq 1
as well, of course. The $?
shell variable is $$?
due to normal Makefile escaping conventions. Note this also rejects exit status 0 (no differences), which is probably what you want.
BTW: it appears this really ought to be:
patch: b.corrected
diff …
b.corrected: b2a.patch
patch …
b2a.patch: a b
diff …
so that modifications of a and b get picked up, and the files regenerated correctly.
Best Answer
Diffs can be more complicated than just comparing one file versus another. The can compare entire directory hierarchies. Consider the example that I want fix a bug in GCC. My change adds a line or two in 4 or 5 files and deletes a handful of lines in those and other files. If I want to communicate these changes to someone, potentially for inclusion into GCC my options are
Copying the entire source tree doesn't make sense, but what about the other two options, which gets at the core of your question. Now consider that someone else also worked on the same file as I did and we both give our changes to someone. How will this person know what we've done and if the changes are compatible (different parts of the file) or conflict (same lines of the file)? He will diff them! The diff can tell him how the files differ from each other and from the unmodified source file. If the diff is what is needed, it just makes more sense to just send the diff in the first place. A diff can also contain changes from more than one file, so while I edited 9 files in total, I can provide a single diff file to describe those changes.
Diffs can also be used to provide history. What if a change three months ago caused a bug I only discovered today. If I can narrow down when the bug was introduced and can isolate it to a specific change, I can use the diff to "undo" or revert the change. This is not something I could as easily do if I were only copying files around.
This all ties into source version control where programs may record files history as a series of diffs from the time it was created until today. The diffs provide history (I can recreate the file as it was on any particular day), I can see who to blame for breaking something (the diff has an owner) and I can easily submit changes to upstream projects by giving them specific diffs (maybe they are only interested in one change when I've made many).
In summary, yes,
cp
is easier thandiff
andpatch
, but the utility ofdiff
andpatch
is greater thancp
for situations where how files change is important to track.