Monades

Weekly Command: comparing files line by line with diff

May 29th, 2018 weekly-command xnix

The basics

diff [option] [files]

diff outputs the differences between two files, line by line. For files that are identical it produces no output, for binary files only reports if they are different or not.

The set of differences produced by diff is often called a diff or patch, and this output can be used later on by the patch command to change other files.

Play by play

Before digging into the examples, let’s define two files that will help us to illustrate some concepts.

To keep the conceptual overhead as low as possible, the files are with-text.js and without-text.js to represent if the text variable is present or not.

File with-text.js:

function example (text) {
  console.log("====")
  console.log(text)
}

File without-text.js:

function something () {
  console.log("====")
}

Default output

By default, diff outputs a list of all the lines that are different between the files, one after the other, alongside with useful information about what changed.

A change can be:

For every line in which diff finds a change, it outputs:

In a more concrete example, if you run:

$ diff with-text.js without-text.js

1c1
< function example (text) {
---
> function something () {
3d2
<   console.log(text)

You get:

Are you able to deduce what the rest of the lines are expressing in the output?

Side by side comparison

Apart from the default output format, you can specify the --side-by-side (short -y) to produce a side-by-side view of what changed.

This format is more visual and can be easier to understand at first sight, for example:

$ diff with-text.js without-text.js --side-by-side

function example (text) {             | function something () {
  console.log("====")                     console.log("====")
  console.log(text)                   <
}                                       }

Working with directories

A very powerful feature of diff is the ability to work with directories. It’s important to note that actual contents of directories are never compared as if they were a file, instead diff uses the following rules:

Colorised output

Since version 3.4 (launched around August of 2016), diff supports the --color flag print colorised output in the terminal.

Reading standard input

If you provide - as a file name, diff will use it for text read from the standard input. As a special case, diff - - compares a copy of standard input to itself.

Omitting differences

diff also provides ways to suppress differences between files that may not be important to you, common examples of this are changes in the amount of white space between words or lines.

Flag Description
-i --ignore-case Ignore case differences in file contents.
--ignore-file-name-case Ignore case when comparing file names.
--no-ignore-file-name-case Consider case when comparing file names.
-E --ignore-tab-expansion Ignore changes due to tab expansion.
-b --ignore-space-change Ignore changes in the amount of white space.
-w --ignore-all-space Ignore all white space.
-B --ignore-blank-lines Ignore changes whose lines are all blank.
-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE.

Using the right tool for the job

While diff awesome, it’s not always the right tool for the job, here are some better fits for different scenarios:



Subscribe

I try to post once a week interesting stuff about programming, *nix, and the web. If you’d like to be notified when a new post goes out, you can subscribe with the form below.


Roberto Dip