12

I wanted to format the Unix files conditionally, I am currently working on diff command and wanted to know if it is possible to format the text of the diff command output.

Example:

Matched values should be displayed in green.
Unmatched values should be displayed in red.

Suppose I have two files file1 and file2 and my command is diff file1 file2.

Now I wanted that suppose output contain 5 mismatch then those mismatch should be displayed in Red color. How to achieve this using unix?

In short "Change color to red for the output of diff command for values which mismatch"

  • 2
    Possible duplicate of this – FloHimself Apr 16 '15 at 10:18
  • The terms "match" and "mismach" are a bit confusing. Anyway, there's the --color option now in diff 3.4 and later. – Gerry Lufwansa Aug 10 '17 at 2:48

10 Answers 10

19

If you have access to GNU diff you can use its --X-group-format options to get that effect without any additional tools:

diff --old-group-format=$'\e[0;31m%<\e[0m' \
     --new-group-format=$'\e[0;31m%>\e[0m' \
     --unchanged-group-format=$'\e[0;32m%=\e[0m' \
     file1 file2

That uses ANSI colour escape codes to get red and green, with ANSI-C quoting in the shell to access the \e escapes.

--old-group-format and --new-group-format identify non-matching lines and insert them between red and colour reset codes using %< and %>, while --unchanged-group-format inserts matching lines between green and reset codes.

You can also use --old-line-format (etc), at the expense of redundant colour escapes on every line: --old-line-format=$'\e[0;31m%L\e[0m'.

  • when I run it gives diff: 0653-821 illegal option -- - diff: 0653-821 illegal option -- o diff: 0653-821 illegal option -- d diff: 0653-821 illegal option -- - diff: 0653-821 illegal option -- g diff: 0653-821 illegal option -- o like errors. – Aman Apr 16 '15 at 11:26
  • Hormer when i am running your commands as by one line at a time it is giving new line no output -bash-4.2$ --new-group-format=$'\e[0;31m%>\e[0m' \ > – Aman Apr 16 '15 at 11:32
  • May I configure that by default? – Eugen Konkov Jul 6 '18 at 11:22
  • @EugenKonkov You could set up an alias or function in your shell to run that for diff. – Michael Homer Jul 6 '18 at 19:35
14

diff --color option was added GNU diffutils 3.4 (2016-08-08)

This is the default diff implementation on most distros, which will soon be getting it.

On 3.5 it looks like this:

enter image description here

with:

diff --color -u \
  <(seq 6 | sed 's/$/ a/') \
  <(seq 8 | grep -Ev '^(2|3)$' | sed 's/$/ a/')

I have also requested word level diff as from diff-highlight at: [Diffutils-devel] Add a flag to produce colored output like git's diff-h | lists.gnu.org

Apparently added in commit c0fa19fe92da71404f809aafb5f51cfd99b1bee2 (Mar 2015).

  • 1
    Excellent! To enable this by default: alias diff='diff --color=auto' – Tom Hale Feb 20 '17 at 12:26
  • 1
    Here is the documentation. – Alexey Apr 12 '17 at 14:12
5

Try colordiff file1 file2

Availability of colordiff with your Linux/BSD distribution

Those running Debian or Ubuntu (or any of their derivatives) can probably just use "apt-get install colordiff" to download and install; colordiff is also packaged for a number of other Linux, UNIX and BSD distributions and operating systems.

(Quote from http://www.colordiff.org/)

  • 1
    Perfect. For me, diff --color=auto was only colourising line markers and the first line of each +/- section. Piping to less -SR makes for easy browsing. – Walf Oct 18 '18 at 1:03
3

Coloured, word-level diff ouput

Here's what you can do with the the below script and diff-highlight:

Coloured diff screenshot

#!/bin/sh -eu

# Use diff-highlight to show word-level differences

diff -U3 --minimal "$@" |
  sed 's/^-/\x1b[1;31m-/;s/^+/\x1b[1;32m+/;s/^@/\x1b[1;34m@/;s/$/\x1b[0m/' |
  diff-highlight

(Credit to @retracile's answer for the sed highlighting)

0

You should have a look at the hl command available on github : git clone http://github.com/mbornet-hl/hl and on : http://www.flashnux.com/notes/page_000022_US.html

hl is a Linux command written in C, especially designed to color a text file or the output of a command. You can use up to 42 colors simultaneously, and use a configuration file to simplify command lines. You can colorize the output of every command that can be piped to another one. And if you know what regular expressions are, it will be very easy for you to use. You can use the man page to understand how to use it.
hl is very easy to use and to configure. You even can use the hl_generic script to colorize commands output without modifying their syntax.
You can, for example, colorize the output of the diff command just by typing your usual command :

diff file1 file2

If you need some help, just send me an e-mail.
Regards.

0

Either you can use

1.diff --color=auto file1 file2

2.colordiff file1 file2

3.My Favourite: git diff file1 file2 implemented as below :

I currently use and recommend is, either using git diff or piping its output with colordiff by using :

diff() { git diff --no-index "$1" "$2" | colordiff; }

  • I like git diff --no-index too but I think files need to be seekable. (At least, doesn't work with bash process substitution for me) – Karl Aug 7 '18 at 7:06
  • @Karl Figure that part out yourself, maybe there is a Terminal setting that does it (or) some other way to make it seekable. I've been using git diff from a long time and the file is seekable for me, otherwise there'd be no use of me doing it right. – himanshuxd Aug 7 '18 at 17:26
  • 2
    Perhaps I wasn't clear very clear. As a (silly) example, this works for me diff --color <(ls | head -n+3) <(ls | tail -n +5) but not with git diff. Admittedly, not a common case or too hard to work around. – Karl Aug 8 '18 at 2:11
0

Just a note: to get the "side-by-side" output you need "--color=always". You can also paginate it with less and retain the colored output:

diff -y --color=always file1 file2 | less -R

And yet another hint: try to keep the "--color=always" switch at the end. Reason? With dmesg from util-linux 2.27.1:

dmesg --human --color=always | less -R    # works
dmesg --color=always --human | less -R    # doesn't work
0

There is a really neat tool built with python on Github at the moment called icdiff. Produces nice coloured outputs which are also “severity” aware. I use it all the time, well worth checking out.

0

This script uses the standard pre-version 3.4 diff (it should work with any version of diff) and colorizes the output without changing the output format in any way. It works with the latest version of RHEL (version 7.5) which has GNU diff version 3.3. Just put it in your ~/bin directory or anywhere else in your path (I suggest calling it "cdiff").

#!/bin/bash
file1color="$(tput setaf 1)"
file2color="$(tput setaf 2)"
sepcolor="$(tput setaf 6)"
reset="$(tput sgr0)"
diff $* |sed -e "s/^\\(<.*\$\\)/$file1color\\1$reset/;s/^\\(>.*\$\\)/$file2color\\1$reset/;s/^\\(---\$\\)/$sepcolor\\1$reset/"
0

if you have vim installed, you can do diff file1 file2 | vim -

Vim will recognise diff format and give it proper coloring. The dash at the end is to let vim accept input from diff command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.