diff - “The difference between "try" and "triumph" is just a little "umph".” ― Marvin Phillips

mail

diff

Usage :

Compare 2 files : diff file1 file2
diff can also be used to compare 2 directories to list :
  • which files exist only once
  • differences between files that are found in both directories

Flags :

Flag Usage
-b --ignore-space-change ignore changes in the amount of white space
-B --ignore-blank-lines ignore changes where lines are all blank
-c n output n (default : 3) lines of context (details)
-i --ignore-case ignore case in file content (don't mix this option up with --ignore-file-name-case)
-q --brief list only name of files having differences
-r compare files recursively when file1 and file2 are directories.
--suppress-common-lines Do not output common lines.
-u n -U n output n lines of unified context (n defaults to 3) (details)
-w --ignore-all-space ignore all white space
-W n --witdh=n Display at most n print columns (defaults to 130, see tput cols)
-x pattern --exclude=pattern ignore files matching pattern
-y --side-by-side output in 2 columns
-Z --ignore-trailing-space ignore white space at line end

Example :

Compare 2 files side by side :

vimdiff file1 file2 is a pretty decent replacement for the diff [options] file1 file2 commands shown below .
  • diff --color=always -Bbiy -W $(tput cols) file1 file2 | less -R
  • fileA='inventory_CW_STG_PCK.ini'
    fileB='inventory_FE_BCR.ini'
    diff --color=always --suppress-common-lines -Bbiy -W $(tput cols) "$fileA" "$fileB" | less -R
    All lines output with this command syntax have differences, even if they are not color-highlighted.

Meaning of the "middle screen" characters output by diff --side-by-side :

character usage
(nothing) no difference, just showing the line for context
| difference found between line of file1 (left) and line of file2 (right)
< only in file1
> only in file2
( only in file1 but ignored
) only in file2 but ignored
Examples :
  • myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut' > "$myFile1"; echo -e 'apple\nbanana\ncarrot' > "$myFile2"; diff --suppress-common-lines --color=always -Bbiy -W $(tput cols) "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
    coconut						|	carrot
  • myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut\nduku' > "$myFile1"; echo -e 'apple\nbanana\ncoconut' > "$myFile2"; diff --suppress-common-lines --color=always -Bbiy -W $(tput cols) "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
    duku						<

Explanation of cryptic output such as 14c115,116 (source) :

Default output :

  • myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut' > "$myFile1"; echo -e 'apple\nbanana\ncoconut' > "$myFile2"; diff "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
    Outputs nothing because files are identical.
  • myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut' > "$myFile1"; echo -e 'apple\nbanana\ncarrot' > "$myFile2"; diff "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
    3c3
    < coconut
    ---
    > carrot
    explanations :
    • 1st line : nXn or n,mXn,m :
      • n or n,m : line / range of lines
      • X : what to do to line of file1 to make it become line of file2 (when running diff file1 file2) :
        output usage detail
        a add nam : after line n of file1, add line m of file2
        c change ncn : change line n of file1 into line n of file2
        d delete ndm : delete line n of file1 so that file1 and file2 match at line m
    • other lines :
      < 		lines of file1
      ---		separator
      > 		lines of file2
  • myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut' > "$myFile1"; echo -e 'apple\nbanana\ncoconut\nduku' > "$myFile2"; diff "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
    3a4
    > duku
    In file1, after line 3, add the shown line so that it matches line 4 of file2
  • myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut\nduku' > "$myFile1"; echo -e 'apple\nbanana\ncoconut' > "$myFile2"; diff "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
    4d3
    < duku
    In file1, delete line 4 shown below, so that it matches line 3 of file2

Context output :

This is enabled with the -c flag.
  • myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut' > "$myFile1"; echo -e 'apple\nbanana' > "$myFile2"; diff -c "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
    *** /tmp/tmp.xn4tkVqjXD 2021-02-03 08:54:11.000000000 +0100
    --- /tmp/tmp.BpdMjolQIN 2021-02-03 08:54:11.000000000 +0100
    ***************
    *** 1,3 ****
      apple
      banana
    - coconut
    --- 1,2 ----
  • myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut' > "$myFile1"; echo -e 'apple\napricot\nbanana\ncarrot' > "$myFile2"; diff -c "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
    *** /tmp/tmp.OUTUkSkX5Z 2021-02-03 08:58:43.000000000 +0100
    --- /tmp/tmp.IsEgTXzyuc 2021-02-03 08:58:43.000000000 +0100
    ***************
    *** 1,3 ****
      apple
      banana
    ! coconut
    --- 1,4 ----
      apple
    + apricot
      banana
    ! carrot
Still in the idea of what to do to file1 to make it look like file2 :
  • + : line to add
  • - : line to remove
  • ! : line changed

Unified output :

This is enabled with the -u flag.
myFile1=$(mktemp); myFile2=$(mktemp); echo -e 'apple\nbanana\ncoconut' > "$myFile1"; echo -e 'apple\nbanana\ncarrot' > "$myFile2"; diff -u "$myFile1" "$myFile2"; for i in "$myFile1" "$myFile2"; do [ -f "$i" ] && rm "$i"; done
--- /tmp/tmp.rxfT2dhbd7 2021-02-03 09:09:56.000000000 +0100
+++ /tmp/tmp.G8Ql2Fp4fy 2021-02-03 09:09:56.000000000 +0100
@@ -1,3 +1,3 @@
 apple
 banana
-coconut
+carrot
This outputs differences with line / range and +, -, , like git diff does.