Colorizing your terminal and shell environment?
Solution 1
Here are a couple of things you can do:
Editors + Code
A lot of editors have syntax highlighting support. vim
and emacs
have it on by default. You can also enable it under nano
.
You can also syntax highlight code on the terminal by using Pygments as a command-line tool.
grep
grep --color=auto
highlights all matches. You can also use export GREP_OPTIONS='--color=auto'
to make it persistent without an alias. If you use --color=always
, it'll use colour even when piping, which confuses things.
ls
ls --color=always
Colors specified by:
export LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33'
(hint: dircolors
can be helpful)
PS1
You can set your PS1 (shell prompt) to use colours. For example:
PS1='\e[33;1m\u@\h: \e[31m\W\e[0m\$ '
Will produce a PS1 like:
[yellow]lucas@ubuntu: [red]~[normal]$
You can get really creative with this. As an idea:
PS1='\e[s\e[0;0H\e[1;33m\h \t\n\e[1;32mThis is my computer\e[u[\u@\h: \w]\$ '
Puts a bar at the top of your terminal with some random info. (For best results, also use alias clear="echo -e '\e[2J\n\n'"
.)
Getting Rid of Escape Sequences
If something is stuck outputting colour when you don't want it to, I use this sed
line to strip the escape sequences:
sed "s/\[^[[0-9;]*[a-zA-Z]//gi"
If you want a more authentic experience, you can also get rid of lines starting with \e[8m
, which instructs the terminal to hide the text. (Not widely supported.)
sed "s/^\[^[8m.*$//gi"
Also note that those ^[s should be actual, literal ^[s. You can type them by pressing ^V^[ in bash, that is Ctrl + V, Ctrl + [.
Solution 2
I also use:
export TERM=xterm-color
export GREP_OPTIONS='--color=auto' GREP_COLOR='1;32'
export CLICOLOR=1
export LSCOLORS=ExFxCxDxBxegedabagacad
And if you like colorizing your prompt, defined color vars can be useful:
export COLOR_NC='\e[0m' # No Color
export COLOR_BLACK='\e[0;30m'
export COLOR_GRAY='\e[1;30m'
export COLOR_RED='\e[0;31m'
export COLOR_LIGHT_RED='\e[1;31m'
export COLOR_GREEN='\e[0;32m'
export COLOR_LIGHT_GREEN='\e[1;32m'
export COLOR_BROWN='\e[0;33m'
export COLOR_YELLOW='\e[1;33m'
export COLOR_BLUE='\e[0;34m'
export COLOR_LIGHT_BLUE='\e[1;34m'
export COLOR_PURPLE='\e[0;35m'
export COLOR_LIGHT_PURPLE='\e[1;35m'
export COLOR_CYAN='\e[0;36m'
export COLOR_LIGHT_CYAN='\e[1;36m'
export COLOR_LIGHT_GRAY='\e[0;37m'
export COLOR_WHITE='\e[1;37m'
And then my prompt is something like this:
case $TERM in
xterm*|rxvt*)
local TITLEBAR='\[\033]0;\u ${NEW_PWD}\007\]'
;;
*)
local TITLEBAR=""
;;
esac
local UC=$COLOR_WHITE # user's color
[ $UID -eq "0" ] && UC=$COLOR_RED # root's color
PS1="$TITLEBAR\n\[${UC}\]\u \[${COLOR_LIGHT_BLUE}\]\${PWD} \[${COLOR_BLACK}\]\$(vcprompt) \n\[${COLOR_LIGHT_GREEN}\]→\[${COLOR_NC}\] "
$(vcprompt) is calling a python script in my ~/sbin which prints version control information about the current path. It includes support for Mercurial, Git, Svn, Cvs, etc. The author of the script has the source here.
This is the full source of my prompt configuration:
Solution 3
grep
and ls
have already been mentioned, if you want a lot more colors check out Generic Coloriser, its initial purpose was to colorize logfiles, but right out of the box it also colorizes ping
, traceroute
, gcc
, make
, netstat
, diff
, last
, ldap
, and cvs
.
It's easily extended if you know regexes. I've added ps
and nmap
to the list (if you get into grc
I'll be more than glad to share the .conf files for those two tools)
(Btw, to install it via synaptic
, pacman
, and alike you might have better luck searching for "grc")
Solution 4
I've honed my .bashrc over the years to work on both OSX and Ubuntu.
I've also reduced it in size to 28 lines with compact condition statements.
With it, my PS1 prompt looks like:
with time in red, username in green, machine name in light blue, pwd in darker blue and git branch in yellow.
Feature of my PS1 prompt:
- shows git branch!
- long directory paths (more than 6 elements) are 'trimmed' to show top 3 and bottom 3 directories with
_
between then (that's thepwd sed
part of LOCATION). - carriage return at the end so that prompt is always on the left!
The relevant lines from my .bashrc
file are:
git_branch () { git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'; }
HOST='\033[02;36m\]\h'; HOST=' '$HOST
TIME='\033[01;31m\]\t \033[01;32m\]'
LOCATION=' \033[01;34m\]`pwd | sed "s#\(/[^/]\{1,\}/[^/]\{1,\}/[^/]\{1,\}/\).*\(/[^/]\{1,\}/[^/]\{1,\}\)/\{0,1\}#\1_\2#g"`'
BRANCH=' \033[00;33m\]$(git_branch)\[\033[00m\]\n\$ '
PS1=$TIME$USER$HOST$LOCATION$BRANCH
PS2='\[\033[01;36m\]>'
For ls with colors when available and no errors when not (i.e. OSX):
ls --color=al > /dev/null 2>&1 && alias ls='ls -F --color=al' || alias ls='ls -G'
Solution 5
Colors for man pages (more detail):
function _colorman() {
env \
LESS_TERMCAP_mb=$'\e[1;35m' \
LESS_TERMCAP_md=$'\e[1;34m' \
LESS_TERMCAP_me=$'\e[0m' \
LESS_TERMCAP_se=$'\e[0m' \
LESS_TERMCAP_so=$'\e[7;40m' \
LESS_TERMCAP_ue=$'\e[0m' \
LESS_TERMCAP_us=$'\e[1;33m' \
LESS_TERMCAP_mr=$(tput rev) \
LESS_TERMCAP_mh=$(tput dim) \
LESS_TERMCAP_ZN=$(tput ssubm) \
LESS_TERMCAP_ZV=$(tput rsubm) \
LESS_TERMCAP_ZO=$(tput ssupm) \
LESS_TERMCAP_ZW=$(tput rsupm) \
GROFF_NO_SGR=1 \
"$@"
}
alias man="LANG=C _colorman man"
function perldoc() { command perldoc -n less "$@" |man -l -; }
Colors for grep (1;32
is bright green, see other posts here for other colors):
GREP_OPTS='--color=auto' # for aliases since $GREP_OPTIONS is deprecated
GREP_COLOR='1;32' # (legacy) bright green rather than default red
# (new) Matching text in Selected line = green, line numbers dark yellow
GREP_COLORS="ms=${GREP_COLOR}:mc=${GREP_COLOR}:ln=33"
alias grep='grep $GREP_OPTS'
alias egrep='grep -E $GREP_OPTS'
alias fgrep='LC_ALL=C grep -F $GREP_OPTS'
Using LC_ALL=C
for fgrep can provide a 140x performance boost
More colors for GNU ls:
# use the config at ~/.dircolors if it exists, otherwise generate anew
eval "$( dircolors --sh $(find ~/.dircolors -size +0 2>/dev/null) )"
# Usage: _ls_colors_add BASE NEW [NEW...]
# Have LS color given NEW extensions the way BASE extension is colored
_ls_colors_add() {
local BASE_COLOR="${LS_COLORS##*:?.$1=}" NEW
if [ "$LS_COLORS" != "$BASE_COLOR" ]; then
BASE_COLOR="${BASE_COLOR%%:*}"
shift
for NEW in "$@"; do
if [ "$LS_COLORS" = "${LS_COLORS#*.$NEW=}" ]; then
LS_COLORS="${LS_COLORS%%:}:*.$NEW=$BASE_COLOR:"
fi
done
fi
export LS_COLORS
}
_ls_colors_add zip jar xpi # archives
_ls_colors_add jpg ico JPG PNG webp # images
_ls_colors_add ogg opus # audio (opus now included by default)
export CLICOLOR=1 # BSD auto-color trigger (like ls -G but for everything)
if ls -ld --color=auto / >/dev/null 2>&1
then alias ls="ls -ph --color=auto"
else alias ls="ls -ph"
fi
Install grc
(Generic Colouriser) and add it to your aliases:
if type grc grcat >/dev/null 2>&1; then
colourify() { # using this as a function allows easier calling down lower
if [[ -t 1 || -n "$CLICOLOR_FORCE" ]]
then ${GRC:-grc} -es --colour=auto "$@"
else "$@"
fi
}
# loop through known commands plus all those with named conf files
for cmd in g++ head ld ping6 tail traceroute6 `locate grc/conf.`; do
cmd="${cmd##*grc/conf.}" # we want just the command
type "$cmd" >/dev/null 2>&1 && alias "$cmd"="colourify $cmd"
done
# This needs run-time detection. We even fake the 'command not found' error.
configure() {
if [[ -x ./configure ]]; then
colourify ./configure "$@"
else
echo "configure: command not found" >&2
return 127
fi
}
unalias ll 2>/dev/null
ll() {
if [[ -n "$CLICOLOR_FORCE" || -t 1 ]]; then # re-implement --color=auto
ls -l --color=always "$@" |grcat conf.ls
return ${PIPESTATUS[0]} ${pipestatus[1]} # exit code of ls via bash or zsh
fi
ls -l "$@"
}
fi
Colors for diff: Too much content for a function, use a script and alias it in your rc file (unnecessary if you installed grc
):
#!/usr/bin/perl
use strict;
use warnings;
open (DIFF, "-|", "diff", @ARGV) or die $!;
my $ydiff = 1;
while (<DIFF>) {
if (not -t 1) {
print;
next;
}
chomp;
$ydiff = 0 if /^[ <>\@+-]/ or ($. == 1 && /^\d+[a-z]{1,5}\d+$/);
my $color = "";
if (! $ydiff && /^[\@+-<>]/) {
$color = (/^[<-](?!--$)/ ? 1 : /^[+>]/ ? 2 : 5);
} elsif ($ydiff && /\t {6}([<|>])(?:\t|$)/) {
$color = ($1 eq "<" ? 1 : $1 eq ">" ? 2 : 4);
}
$color ? printf ("\e[1;3%dm%s\e[0;0m\n",$color,$_) : print "$_\n";
}
close DIFF;
Colors for bash prompt:
# Shorten home dir, Cygwin drives, paths that are too long
function PSWD() {
local p="$*" space A B cols="${COLUMNS:-`tput cols 2>/dev/null || echo 80`}"
p="${p/$HOME/\~}" # shrink home down to a tilde
if [ -d /cygdrive ] && [ "${p#/cygdrive/?/}" != "$p" ]; then
p="${p:10:1}:${p:11}" # /cygdrive/c/hi -> c:/hi
fi
space="$((${#USER}+${#HOSTNAME}+6))" # width w/out the path
if [ "$cols" -lt 60 ]; then echo -n "$N "; space=-29; p="$p$N\b"; fi
if [ "$cols" -lt "$((space+${#p}+20))" ]; then # < 20 chars for the command
A=$(( (cols-20-space)/4 )) # a quarter of the space (-20 for cmd)
if [ $A -lt 4 ]; then A=4; fi # 4+ chars from beginning
B=$(( cols-20-space-A*2 )) # half (plus rounding) of the space
if [ $B -lt 8 ]; then B=8; fi # 8+ chars from end
p="${p:0:$A}..${p: -$B}"
fi
echo "$p"
}
PSC() { printf $'\[\e[%sm\]' "${*:-0;0}"; }
PR="0;32" # default color used in prompt is green
if [ "$(id -u)" = 0 ]; then
sudo=41 # root is red background
elif [ "$USER" != "${SUDO_USER:-$USER}" ]; then
sudo=31 # not root, not self: red text
else sudo="$PR" # standard user color
fi
PROMPT_COMMAND='[ $? = 0 ] && PS1=${PS1[1]} || PS1=${PS1[2]}'
PSbase="$(PSC $sudo)\u$(PSC $PR)@\h $(PSC 33)\$(PSWD \w)"
PS1[1]="$PSbase$(PSC $PR)\$ $(PSC)"
PS1[2]="$PSbase$(PSC 31)\$ $(PSC)"
PS1="${PS1[1]}"
unset sudo PR PSbase
Related videos on Youtube
Mark Norgren
Updated on September 17, 2022Comments
-
Mark Norgren over 1 year
I spend most of my time working in Unix environments and using terminal emulators. I try to use color on the command line, because color makes the output more useful and intuitive.
What options exist to add color to my terminal environment? What tricks do you use? What pitfalls have you encountered?
Unfortunately, support for color varies depending on terminal type, OS, TERM setting, utility, buggy implementations, etc.
Here are some tips from my setup, after a lot of experimentation:
- I tend to set
TERM=xterm-color
, which is supported on most hosts (but not all). - I work on a number of different hosts, different OS versions, etc. I use everything from macOS X, Ubuntu Linux, RHEL/CentOS/Scientific Linux and FreeBSD. I'm trying to keep things simple and generic, if possible.
- I do a bunch of work using GNU
screen
, which adds another layer of fun. - Many OSs set things like
dircolors
and by default, and I don't want to modify this on a hundred different hosts. So I try to stick with the defaults. Instead, I tweak my terminal's color configuration. -
Use color for some Unix commands (
ls
,grep
,less
,vim
) and the Bash prompt. These commands seem to use the standard "ANSI escape sequences". For example:alias less='less --RAW-CONTROL-CHARS' export LS_OPTS='--color=auto' alias ls='ls ${LS_OPTS}'
I'll post my
.bashrc
and answer my own question Jeopardy Style.-
Admin over 9 yearsfyi my approach (see answer below) addresses issues with OSX and Linux differences, for example color on one is ls -G and on the other is ls --color-auto
-
Admin over 6 yearsDid anybody see a tool to color columns? That is a
column -t --color
? -
Admin over 2 years@TomášPospíšek have you looked into grc ?
-
Admin over 2 yearsthanks for the pointer @amrx
- I tend to set
-
tsvallender almost 14 yearsOr if you want to use ZSH, Phil Gold's prompt at aperiodic.net/phil/prompt is a work of art.
-
manatwork over 12 yearsPlease specify your shell. The question's only shell specific tag is bash, but I feel your code is not
bash
. -
Mischa Arefiev over 12 years@manatwork: sorry, forgot to mention that it was Zsh. Updated my post.
-
Xander Dunn over 11 yearsSee here for the solution to a line problem I got when I used the above PS1: stackoverflow.com/questions/5087036/…
-
sophie668 almost 11 yearsThe first PS1 line should read like this:
PS1='\e[33;1m\u@\h: \e[31m\W\e[0m\$ '
. There is a superfluous x after the fourth backslash. -
Kris over 9 yearsI've updated the answer to reflect the escaped brackets for the colors in the prompt. Thanks!
-
Adam Katz over 9 years
$LSCOLORS
and$CLICOLOR
are for BSD ls. GNU ls (Linux) uses$LS_COLORS
with a different syntax. As GNU feels like home to me, I useLSCOLORS=exgxfxDacxBaBaCaCaeaEa
to mimic GNU's colors on BSD. -
Adam Katz over 9 years
grc
now supportsps
by default. I'd be interested in yournmap
colorings. See also my answer for aliasing all of these in a way that will absorb new commands when you upgrade grc. -
Sygo over 9 yearsI noticed that. here's my conf.nmap (and everything else, really) gist.github.com/sygo/844982#file-conf-nmap - I noticed you work in infosec, you might find conf.hexdump interesting, I haven't finished it yet though.
-
Adam Katz over 9 yearsThanks @Sygo. I've forked and revised your gist. I've never actually committed data with git (let alone github's gists) and I cannot figure out how to propose merging it back to you (I'm guessing this is because gists are too simplified).
-
Sygo over 9 yearsI suspect you can't because it's a gist and not a proper repository. I did check out your fork though and I'm definitely giving your version a go. I'm curious as what that hex dump one will turn into...
-
mattts about 9 yearsColors are available for
ls
on OS X, but it is done by usingexport CLICOLOR=1
. -
Admin almost 8 yearsIf I could, I would downvote this for the Oh-My-ZSH suggestion. As a systems engineer who works extensively in the Terminal, and as somebody who tried to adopt zsh/oh-my-zsh into my workflow, I can honestly say I would never recommend ZSH to anyody. Sure, you can symlink zsh to a file named after any other shell and emulate that shell, but when you do that it doesn't read your .bashrc, .bash_profile, etc. Also, you cannot put
emulate bash
in your .zprofile or .zshrc files. For anybody who works with advanced features in BASH, there are many subtleties that will bite you. BASH is a better sh. -
Admin almost 8 yearsThe only thing that ZSH has out of the box that is better than BASH is command completion, but even that is programmable in BASH. Maybe somebody who doesn't use the shell except for occasional mundane tasks should adopt ZSH, but it's not for anybody who needs to use the shell extensively. the
=~
operator can bite you, the way ZSH handles arrays can bite you, etc. After using ZSH/Oh-My-ZSH for about 9 months I had enough of it. I was using a custom theme that I wrote myself, I ported it to BASH and wrote my own git promptline and I've never looked back. Now I no longer worry about portability -
Admin over 7 years"it has one of the most powerfull console features that I saw. One of them is picking theme for your terminal."
-
JdeBP over 7 yearsNonetheless, ThomasW is correct to point out that the answer is erroneous in saying that colours are not available with
ls
on MacOS 10. The answer is also erroneous in that the prompt strings here are in fact faulty. They do not correctly balance\[
and\]
, and have caused problems for at least one person copying this answer. -
Steven Almeroth over 7 years
grep: warning: GREP_OPTIONS is deprecated; please use an alias or script
-
Green almost 7 yearsA screenshot would be nice
-
Adam Katz over 6 yearsUpdate on
$LSCOLORS
GNU parity:LSCOLORS=ExGxFxDaCxDaDaxbxDacad
. -
Adam Katz over 6 yearsMy
PSWD()
function used to be POSIX-compatible but it's so much easier facilitated using bash/zsh substring handling. See revision 6 for the POSIX version, which involves lots of question marks and wasn't at all adaptable to terminal width. I didn't update the screenshot, but it's only a slight change at the 80 character width. -
GKFX over 6 yearsYour values are the same for
COLOR_BLACK
andCOLOR_GREY
. -
Artur Vieira over 6 yearsHello, how do you make the flags, for the prompt path? I am mentioning the rectangular bars with triangle ends Thanks
-
Spencer D over 6 yearsAny fork or alternative links for the
vcprompt
? Seems like it's now a 404. -
Ben about 6 yearsdoes it work in a ubuntu gnu terminal as well?
-
Cyril Chaboisseau almost 6 yearslnav is also a great tool to show colorized logfiles
-
Admin almost 6 years@JonathanHartley, your comment looks like you left it incomplete. ?
-
Admin almost 6 yearsThank you for your concern but my comment says everything I intended to say.
-
Kris over 5 yearsAdded a new link to the source for
vcprompt
as a GitHub gist, and a screen capture of the colorized final prompt. -
Gert van den Berg over 5 yearsWhen using links to external source, you should check the "Provide context for links" part (Quote important parts) of the relevant part of the guide: unix.stackexchange.com/help/how-to-answer
-
Simon C. over 5 yearsThe
ls --color=always
doesn't work. @Michael Durrant' s approach is better for this:ls --color=al > /dev/null 2>&1 && alias ls='ls -F --color=al' || alias ls='ls -G'
-
Simon C. over 5 years
CLICOLOR=1
doesn't work for me with FREEBSD 11.2 -
Adam Katz over 5 years@SimonC. – You might be using GNU utilities on your FreeBSD system rather than the BSD ones.
CLICOLOR=1 ls
should do the same thing asls -G
using BSD (ls -g
on older BSDs). Ifls --color
works (no error), you're using GNU'sls
command and$CLICOLOR
is ignored. -
Simon C. over 5 yearsThanks. It's really strange then. Putting
CLICOLOR=1
in my bashrc doesn't do anything, though when doing echo$CLICOLOR
it tells me it's at when. While definingCLICOLOR=1
just before callingls
as you mentioned in your post works. andls --color
return an "illegal option", suggesting I am indeed using BSDls
... not sure what's happening -
Adam Katz over 5 years@SimonC. – You have to actually load your
~/.bashrc
for any changes to take effect. Either runsource ~/.bashrc
or start a new bash session (launch a terminal or runbash
). -
Simon C. over 5 yearsyes yes I know and did (both things, starting bash again as well as source the rc file from within bash),you can see here, on my side I dont know what I am doing wrong :imgur.com/a/RVkUple
-
Adam Katz over 5 yearsMaybe try running
export CLICOLOR
after you define it. If that works, I'll add it to my answer. -
Teemu Leisti about 5 yearsThe
.bashrc
example is missing the finalfi
, and could be converted to a single-line command:type colordiff &> /dev/null && alias diff='colordiff'
-
amiabl almost 5 yearsYou may need to source the
.bashrc
file for the modification to be effective. You can do it with the following command.source /path/to/.bashrc
-
RadaRK over 2 yearsUse the colors before the parts you want to color. This is where i found this gist.github.com/vratiu/9780109