How to colorize diff on the command line
When I have a diff, how can I colorize it so that it looks good? I want it for the command line, so please no GUI solutions.
emacs does great color diffs in a terminal; is that what you mean by non-GUI? See unix.stackexchange.com/a/613399/80268 .
17 Answers 17
Man pages for diff suggest no solution for colorization from within itself. Please consider using colordiff . It’s a wrapper around diff that produces the same output as diff, except that it augments the output using colored syntax highlighting to increase readability:
- Ubuntu/Debian: sudo apt-get install colordiff
- OS X: brew install colordiff or port install colordiff
Just found that myself :-). It can be piped into less by using less -R , which displays the escape sequences for colors correctly.
Alas, it doesn’t work for the side-by-side output ( -y option to enable) ☹ The vimdiff suggestion below probably a better way
colordiff works well for svn diff | colordiff (i.e. in situations where you only have the diff, not the two files being diffed).
As an update to @Hi-Angel ‘s comment: colordiff has been updated and now includes side by side ( -y ) support.
diff /path/to/a /path/to/b | vim -R -
Or better still, VimDiff (or vim -d , which is shorter to type) will show differences between two, three or four files side-by-side.
Examples:
vimdiff file1 file2 file3 file4
@Jichao: I prefer to learn the commands rather than alias them away. That way I can use them anywhere, even when my dotfiles aren’t available.
@AquariusPower: ctrl-c and ctrl-x have other uses in Vim. ctrl-q is captured by many terminals. See Writing and quitting to find the way that best suits your needs.
vimdiff won’t handle directory diff s. Alternatively, you can save diff to a file, and open it with vim . That way you will have vim colorize it using built-in syntax highlighting facilities.
First, what kind of shell is this? zsh ? I don’t recognize =(. ) construct. Second, I had diff -ur a b in mind.
Actually there seems to be yet another option (which I only noticed recently, when running into the problem described above):
git diff —no-index # output to console instead of opening a pager git —no-pager diff —no-index
If you have Git around (which you already might be using anyway), then you will be able to use it for comparison, even if the files themselves are not under version control. If not enabled for you by default, then enabling color support here seems to be considerably easier than some of the previously mentioned workarounds.
This is neat, but sadly this doesn’t work when the inputs are pipes. For example comparing binary files via git diff <(xxd file1) <(xxd filed) doesn't work.
Oddly, at least one of the files has to be ‘outside the current repository’, according to git help diff . So if your git diff is coming up empty, try cd out of where you are.
diff —color option (added to GNU diffutils 3.4 in 2016-08-08)
This is the default diff implementation on most distributions, which will soon be getting it.
Ubuntu 18.04 (Bionic Beaver) has diffutils 3.6 and therefore has it.
Apparently added in commit c0fa19fe92da71404f809aafb5f51cfd99b1bee2 (Mar 2015).
Word-level diff
Like diff-highlight . It is not possible it seems, but there is a feature request: https://lists.gnu.org/archive/html/diffutils-devel/2017-01/msg00001.html
ydiff does it though. See below.
ydiff side-by-side word level diff
python3 -m pip install --user ydiff diff -u a b | ydiff -s
If the lines are too narrow (default 80 columns), fit to the screen with:
Contents of the test files:
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
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
ydiff Git integration
ydiff integrates with Git without any configuration required.
From inside a Git repository, instead of git diff , you can do just:
Tested on Ubuntu 16.04 (Xenial Xerus), Git 2.18.0, and ydiff 1.1.
In that mailing list thread: There is no word-highlighting, yet — any updates? This is what I came to this question for (I want grep —color -like diff output).
@i336_ no updates unfortunately, if I get any, I will update the question. Ping me if you find anything.
And for those occasions when a yum install colordiff or an apt-get install colordiff is not an option due to some insane constraint beyond your immediate control, or you’re just feeling crazy, you can reinvent the wheel with a line of sed:
sed 's/^-/\x1b[41m-/;s/^+/\x1b[42m+/;s/^@/\x1b[34m@/;s/$/\x1b[0m/'
Throw that in a shell script and pipe unified diff output through it.
It makes hunk markers blue and highlights new/old filenames and added/removed lines in green and red background, respectively. 1 And it will make trailing space 2 changes more readily apparent than colordiff can.
1 Incidentally, the reason for highlighting the filenames the same as the modified lines is that to correctly differentiate between the filenames and the modified lines requires properly parsing the diff format, which is not something to tackle with a regex. Highlighting them the same works «well enough» visually and makes the problem trivial. That said, there are some interesting subtleties.
2 But not trailing tabs. Apparently tabs don’t get their background set, at least in my xterm. It does make tab vs. space changes stand out a bit though.
What do the different colors mean in ls?
What do the different colours in Ubuntu’s ls command mean? For example, when I type the ls command in one of my folders, I get one of the files in light green, the other (which is a folder) in blue with green highlighting. What do those colours mean, and there is any manual about all the colours?
5 Answers 5
- Blue: Directory
- Green: Executable or recognized data file
- Cyan (Sky Blue): Symbolic link file
- Yellow with black background: Device
- Magenta (Pink): Graphic image file
- Red: Archive file
- Red with black background: Broken link
- To turn the color off, you have to comment out the following lines in .bashrc .
# enable color support of ls and also add handy aliases #if [ -x /usr/bin/dircolors ]; then # test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" # alias ls='ls --color=auto' # #alias dir='dir --color=auto' # #alias vdir='vdir --color=auto' # # alias grep='grep --color=auto' # alias fgrep='fgrep --color=auto' # alias egrep='egrep --color=auto' #fi
eval $(echo "no:global default;fi:normal file;di:directory;ln:symbolic link;pi:named pipe;so:socket;do:door;bd:block device;cd:character device;or:orphan symlink;mi:missing file;su:set uid;sg:set gid;tw:sticky other writable;ow:other writable;st:sticky;ex:executable;"|sed -e 's/:/="/g; s/\;/"\n/g') < IFS=: for i in $LS_COLORS do echo -e "\e[$m$( x=$; [ "$" ] && echo "$" || echo "$x" )\e[m" done >
You can find out what colours ls uses by looking at the $LS_COLORS variable:
- Turquoise: audio files 1
- Bright Red: Archives and compressed files 2
- Purple: images and videos 3
In addition, files are colourised by attributes:
- aac, au, flac, mid, midi, mka, mp3, mpc, ogg, ra, wav, axa, oga, spx, xspf.
- tar, tgz, arj, taz, lzh, lzma, tlz, txz, zip, z, Z, dz, gz, lz, xz, bz2, bz, tbz, tbz2, tz, deb, rpm, jar, rar, ace, zoo, cpio, 7z, rz.
- jpg, jpeg, gif, bmp, pbm, pgm, ppm, tga, xbm, xpm, tif, tiff, png, svg, svgz, mng, pcx, mov, mpg, mpeg, m2v, mkv, ogm, mp4, m4v, mp4v, vob, qt, nuv, wmv, asf, rm, rmvb, flc, avi, fli, flv, gl, dl, xcf, xwd, yuv, cgm, emf, axv, anx, ogv, ogx.
All this information is contained in the output of dircolors —print-database , but its formatting is rather unreadable.
Here’s a technical explanation of what’s happening:
The colour code consists of three parts:
- The first part before the semicolon represents the text style.
- 00=none, 01=bold, 04=underscore, 05=blink, 07=reverse, 08=concealed.
- 30=black, 31=red, 32=green, 33=yellow, 34=blue, 35=magenta, 36=cyan, 37=white.
Each part can be omitted, assuming starting on the left. i.e. «01» means bold, «01;31» means bold and red. And you would get your terminal to print in colour by escaping the instruction with \33[ and ending it with an m . 33, or 1B in hexadecimal, is the ASCII sign «ESCAPE» (a special character in the ASCII character set). Example:
Prints «Hello World» in bright red.
The command ls with the argument —color=auto (on Ubuntu, ls is an alias for ls —color=auto ) goes through all the file names and tries first to match different types, like Executable, Pipe and so on. It then tries to match regular expressions like *.wav and prints the resulting filename, enclosed in these colour-changing instructions for bash.
Thanks! I was looking at a Git topology visualization question and wondered why some of the characters were being printed.
Full list, with the default setup
- Uncolored (white):
- file
- non-filename text (e.g. permissions in the output of ls -l )
- multi-hardlink file
- image file, video, graphic, etc.
- door
- socket
- block device
- character device
- orphan symlink
- missing file
Note that bold red looks orange, black looks dark grey, cyan looks blue/green, and bold magenta looks purple/pink/lavender.
Script to show colors
#!/bin/bash # For each entry in LS_COLORS, print the type, and description if available, # in the relevant color. # If two adjacent colors are the same, keep them on one line. declare -A descriptions=( [bd]="block device" [ca]="file with capability" [cd]="character device" [di]="directory" [do]="door" [ex]="executable file" [fi]="regular file" [ln]="symbolic link" [mh]="multi-hardlink" [mi]="missing file" [no]="normal non-filename text" [or]="orphan symlink" [ow]="other-writable directory" [pi]="named pipe, AKA FIFO" [rs]="reset to no color" [sg]="set-group-ID" [so]="socket" [st]="sticky directory" [su]="set-user-ID" [tw]="sticky and other-writable directory" ) IFS=: for ls_color in $LS_COLORS; do color="$" type="$" # Add description for named types. desc="$" # Separate each color with a newline. if [[ $color_prev ]] && [[ $color != "$color_prev" ]]; then echo fi printf "\e[%sm%s%s\e[m " "$color" "$type" "$" # For next loop color_prev="$color" done echo
Output with default setup:
I got the descriptions from dircolors -p and man dir_colors , and filled in the gaps with my own research.
The colors and descriptions are the same from at least 14.04 to 17.10.
@FredrickGauss Not explicitly, but «RESET» is the only one that can be abbreviated as «rs», and the color (0) matches.
If you type dircolors ( echo $LS_COLORS also works) from command line you will get a list of codes and colors for lots of filetypes in 1 line. dircolors —print-database shows them 1 line at a time. Here is a short list (I tried to put in the most important ones). At the bottom there is an explanation about what the different codes at the end of each lines represents:
NORMAL 00 # global default, although everything should be something. FILE 00 # normal file DIR 01;34 # directory LINK 01;36 # symbolic link. (If you set this to 'target' instead of a # numerical value, the color is as for the file pointed to.) FIFO 40;33 # pipe SOCK 01;35 # socket DOOR 01;35 # door BLK 40;33;01 # block device driver CHR 40;33;01 # character device driver ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file SETUID 37;41 # file that is setuid (u+s) SETGID 30;43 # file that is setgid (g+s) STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable # archives or compressed (bright red) .tar 01;31 .tgz 01;31 # image formats .jpg 01;35 .jpeg 01;35 .gif 01;35 .bmp 01;35 # audio formats .aac 00;36 .flac 00;36 .ogg 00;36
- Attribute codes: 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
- Text color codes: 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
- Background color codes: 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
If you want to play around with this here is an example on how to set a color for a file:
export LS_COLORS=$LS_COLORS:"*.ogg=01;35":"*.mp3=01;35"
This will set *.ogg and .mp3 to bold magenta . And if you put it in your .bashrc file it will become permanent.