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"
-
2Possible duplicate of thisFloHimself– FloHimself2015年04月16日 10:18:38 +00:00Commented Apr 16, 2015 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– Gerry Lufwansa2017年08月10日 02:48:49 +00:00Commented Aug 10, 2017 at 2:48
15 Answers 15
diff --color
option was added to GNU diffutils 3.4 (2016年08月08日)
This is the default diff
implementation on most distros, which will soon be getting it.
Ubuntu 18.04 has diffutils
3.6 and therefore has it.
On 3.5 it looks like this:
Tested:
diff --color -u \
<(seq 6 | sed 's/$/ a/') \
<(seq 8 | grep -Ev '^(2|3)$' | sed 's/$/ a/')
Apparently added in commit c0fa19fe92da71404f809aafb5f51cfd99b1bee2 (Mar 2015).
Word-level diff
Like diff-highlight
. Not possible it seems, feature request: https://lists.gnu.org/archive/html/diffutils-devel/2017-01/msg00001.html
Related threads:
- https://stackoverflow.com/questions/1721738/using-diff-or-anything-else-to-get-character-level-diff-between-text-files
- diff within a line
- https://superuser.com/questions/496415/using-diff-on-a-long-one-line-file
ydiff
does it though, see below.
ydiff
side-by-side word level diff
https://github.com/ymattw/ydiff
Is this Nirvana?
python3 -m pip install --user ydiff
diff -u a b | ydiff -s
Outcome:
If the lines are too narrow (default 80 columns), fit to screen with:
diff -u a b | ydiff -w 0 -s
Contents of the test files:
a
1
2
3
4
5 the original line the original line the original line the original line
6
7
8
9
10
11
12
13
14
15 the original line the original line the original line the original line
16
17
18
19
20
b
1
2
3
4
5 the original line teh original line the original line the original line
6
7
8
9
10
11
12
13
14
15 the original line the original line the original line the origlnal line
16
17
18
19
20
ydiff
Git integration
ydiff
integrates with Git without any configuration required.
From inside a git repository, instead of git diff
, you can do just:
ydiff -s
and instead of git log
:
ydiff -ls
Tested on Ubuntu 16.04, git 2.18.0, ydiff 1.1.
-
1Excellent! To enable this by default:
alias diff='diff --color=auto'
Tom Hale– Tom Hale2017年02月20日 12:26:05 +00:00Commented Feb 20, 2017 at 12:26 -
2
-
does not work on Centos 7user5359531– user53595312020年05月19日 00:00:01 +00:00Commented May 19, 2020 at 0:00
-
1Does anyone know why the color gets lost if I pipe to
more
? Or how to fix this behavior? (or a better way to slowly scroll through thediff
output?)Tyler R.– Tyler R.2022年01月04日 16:31:58 +00:00Commented Jan 4, 2022 at 16:31 -
1@TylerR. see: superuser.com/questions/117841/…Ciro Santilli OurBigBook.com– Ciro Santilli OurBigBook.com2022年01月04日 17:14:13 +00:00Commented Jan 4, 2022 at 17:14
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– Aman2015年04月16日 11:26:31 +00:00Commented Apr 16, 2015 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– Aman2015年04月16日 11:32:00 +00:00Commented Apr 16, 2015 at 11:32
-
May I configure that by default?Eugen Konkov– Eugen Konkov2018年07月06日 11:22:16 +00:00Commented Jul 6, 2018 at 11:22
-
1@EugenKonkov You could set up an alias or function in your shell to run that for
diff
.Michael Homer– Michael Homer2018年07月06日 19:35:01 +00:00Commented Jul 6, 2018 at 19:35 -
1@Ansa211 That is what the question asked for, rather than traditional colordiff-style output, but you can shift the green escape (32) into
--new-group-format
and drop the unchanged entry entirely to get that (thoughdiff --color
or colordiff is almost certainly better now if you don't have those very specific requirements - and it uses line-by-line colouring sodifff --color ... | less -R
doesn't break it).Michael Homer– Michael Homer2021年01月25日 21:15:07 +00:00Commented Jan 25, 2021 at 21:15
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/)
-
1Perfect. For me,
diff --color=auto
was only colourising line markers and the first line of each+
/-
section. Piping toless -SR
makes for easy browsing.Walf– Walf2018年10月18日 01:03:17 +00:00Commented Oct 18, 2018 at 1:03
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.
-
2'view' (the read-only shortcut to vim) is better suited for this purpose.Anupam Srivastava– Anupam Srivastava2019年10月29日 08:53:21 +00:00Commented Oct 29, 2019 at 8:53
-
this completely wrecked my terminaluser5359531– user53595312020年05月19日 00:02:10 +00:00Commented May 19, 2020 at 0:02
Coloured, word-level diff
ouput
Here's what you can do with the the below script and diff-highlight:
#!/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)
-
1Actually,
diff-highlight
does not do a word-level output. It just detects a common prefix and a common suffix on a changed line. For instance, if several words are changed, it will highlight everything from the first changed word to the last changed word. Moreover, this is effective only when only one line is changed between unchanged lines. In GNU Emacs, diff-mode does much better.vinc17– vinc172022年03月11日 23:32:12 +00:00Commented Mar 11, 2022 at 23:32 -
Installation: pip3 install --user diff-highlightAlexey Shrub– Alexey Shrub2023年05月02日 17:29:51 +00:00Commented May 2, 2023 at 17:29
To change diff's color palette use the --palette
option (diff version 3.4 and higher):
diff --color=always --palette='ad=1;3;38;5;154:de=1;3;38;5;9' file1 file2
Here ad
and de
define the color of added and deleted text respectively. For a detailed description of diff options see man diff
or info diff
.
-
1This is extremely flexible. It's nice to know that I can use whatever palette I want. Thanks.bballdave025– bballdave0252020年06月02日 20:35:41 +00:00Commented Jun 2, 2020 at 20:35
-
+1 I was searching for a
--palette
example, thanks!F. Hauri - Give Up GitHub– F. Hauri - Give Up GitHub2023年09月11日 08:41:26 +00:00Commented Sep 11, 2023 at 8:41 -
Wonderful. Out of curiosity, did you look at the source code to learn of 'ad' and 'de'? I did not find any detailed palette format info in man diff or info diff.François Tonneau– François Tonneau2025年01月11日 15:20:47 +00:00Commented Jan 11 at 15:20
Character-level color diff: Install ccdiff
ccdiff -r /usr/share/dict/words /tmp/new-dict
-
That's the best answer so far. It's not C native, but does the job.Smeterlink– Smeterlink2020年05月22日 23:09:15 +00:00Commented May 22, 2020 at 23:09
-
ccdiff
seems to work well as a diff program, but unfortunately, it cannot color an existing diff (such as a patch).vinc17– vinc172022年03月11日 23:37:01 +00:00Commented Mar 11, 2022 at 23:37
You could use :
diff --color=auto file1 file2
colordiff file1 file2
git diff file1 file2
which is my favorite method
I currently use git diff
or pipe it's output with colordiff
:
diff() { git diff --no-index "1ドル" "2ドル" | colordiff; }
-
1I 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– Karl2018年08月07日 07:06:21 +00:00Commented Aug 7, 2018 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– himanshuxd2018年08月07日 17:26:52 +00:00Commented Aug 7, 2018 at 17:26 -
2Perhaps 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 withgit diff
. Admittedly, not a common case or too hard to work around.Karl– Karl2018年08月08日 02:11:50 +00:00Commented Aug 8, 2018 at 2:11 -
git diff --no-index
already colorizes the output, why on earth do you pass the output tocolordiff
? If the output has no color then you have wrong config, usegit config color.diff auto
to fix itphuclv– phuclv2023年01月25日 03:25:36 +00:00Commented Jan 25, 2023 at 3:25 -
@phuclv at the time which is 2018, I think whatever terminal I was using was not coloring it with
git diff
itself or the color scheme might have been weird without thecolordiff
pipe.himanshuxd– himanshuxd2023年11月22日 21:10:04 +00:00Commented Nov 22, 2023 at 21:10
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/"
-
2And if you don't know off the top of your head what those parms to
tput
mean, do aman terminfo
Mark Stewart– Mark Stewart2020年11月05日 15:53:17 +00:00Commented Nov 5, 2020 at 15:53 -
1This saved me! I am on a system with diff 3.3, so it has no
--color
option (nor can I upgrade, or install colordiff, or anything new). Modifying the --new-line-format and etc. made it hard to keep the lines that normaldiff -u
chooses. This solution was exactly what I need.Ajean– Ajean2022年11月02日 21:58:49 +00:00Commented Nov 2, 2022 at 21:58
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.
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
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.
-
this didn't do anything for me, on WSL Ubuntu 18.04 using Windows Terminal 2zaf187– zaf1872021年05月28日 23:49:02 +00:00Commented May 28, 2021 at 23:49
If you're on an apline linux container and don't want/can't pull down these other tools, this might work in a pinch.
RED="\\033円[0;31m"
GREEN="\\033円[0;32m"
OFF="\\033円[0m"
DIFF=$(diff --label "GOT" <(echo "$OUTPUT") --label "EXPECTED" <(echo "$EXPECTED_OUTPUT"))
printf -- "$(echo "$DIFF" | sed "s|^-|$RED-|g" | sed "s|^+|$GREEN+|g" | sed "s|$|$OFF|g")"
Here's some sample output.
diff 3.4+ can colorize its output in some modes like diff -u
, diff -c
.
Also the pure shell script is available https://github.com/ildar-shaimordanov/colordiff.
It does almost the same work as the Perl https://github.com/daveewart/colordiff.