How can I change the colors of my xterm using Ansi escape sequences?

26

11

I would like to change the colors (background, font, foreground) of my xterm from the commandline. I've heard that this can be done using ANSI escape sequences.

If this is possible:

  • How is it done?
  • Can I use color names or must I use their RGB codes?

Nathan Fellman

Posted 2011-04-13T06:49:12.233

Reputation: 8 152

Answers

29

ANSI escape sequences consist of a sequence of characters beginning with the Escape character, character 27. The next character is often (though not always) an open-square-bracket: [

The echo command can send escape characters if you specify -e and use \e for escape.

The ANSI standard defines 8 colours, plus a bright mode, giving a total of 16 posibilities. The sequence is:

\e[<number>m

Where <number> is one of:

Foreground:

  • 30 Black
  • 31 Red
  • 32 Green
  • 33 Yellow
  • 34 Blue
  • 35 Magenta
  • 36 Cyan
  • 37 White

Background:

  • 40 Black
  • 41 Red
  • 42 Green
  • 43 Yellow
  • 44 Blue
  • 45 Magenta
  • 46 Cyan
  • 47 White

  • 0 Reset all

  • 1 Bold

So to make your foreground red and your background yellow:

$ echo -e "\e[31m\e[43m"

And to enable bold:

$ echo -e "\e[1m"

Of course, you can combine them all together:

$ echo -e "\e[31m\e[43m\e[1m"

There are many many other escape codes for doing other things.

For example - clear the screen and move the cursor to the top-left:

$ echo -e "\e[2J\e[1;1H"

Which is useful when changing the colour:

$ echo -e "\e[31m\e[43m\e[1m\e[2J\e[1;1H"

Which will change the colours, clear the screen, and put the cursor at the top-left. Well, almost the top left. Echo puts a carriage return in, so it moves down a line. You can add -n to echo to prevent this if you're fussy.

If you mess it all up and can't see what you're typing you can reset the terminal colours to normal by pressing:

Ctrl+v [ 0 m Return

At what you hope is the command prompt. It will whinge about an unknown command, but you will be able to see what you're doing again.

Majenko

Posted 2011-04-13T06:49:12.233

Reputation: 29 007

How do I change the color of the cursor to 34 Blue? – trusktr – 2014-06-27T02:48:43.857

can I use color names instead of color codes? – Nathan Fellman – 2011-04-13T14:02:02.063

1No, but you can assign the colour codes to variables. FGRED=31; echo -e "\e[${FGRED}m" – Majenko – 2011-04-13T14:15:46.237

3It should be noted, however, that multiple color code numbers can be separated by ";". So to make your foreground red and your background yellow you can also use the shorter: echo -ne '\e[31;43m' (instead of the above echo -e "\e[31m\e[43m"). – Andreas Spindler – 2013-02-14T15:41:42.227

28

Note that modern Xterms support 32-bit color!

Simple example. To set a nice dark purple background (hey, each to his own) of value #53186f, you do:

echo -ne "\033]11;#53186f\007"

Note that this instantly changes the color of the whole window, not just of the subsequent text. This is especially nice for making a window obviously different after ssh'ing to a server (for example). Put the above 'echo' into your .bashrc and your terminal automatically changes colors when you log into that server (but won't change back when you Ctrl-D out)

You can spend HOURS on the net looking for this - most docs only talk about the original 16 ANSI colors.

Sources: http://www.steike.com/code/xterm-colors/ and http://rtfm.etla.org/xterm/ctlseq.html (look under "Operating System Controls")

Please note: the escape sequence above is valid for XTerms, and may not work for other implementations of "XTerm-like" windowing terminal emulators that may "look" like an XTerm. For example, "gnome-terminal" or "konsole" have different escape sequences, or may not implement color change at all.

Greg

Posted 2011-04-13T06:49:12.233

Reputation: 381

1how is #53186f 32-bit colors. I count 24 bits... – jiggunjer – 2017-02-24T04:50:48.163

Does anyone know how to accomplish the same thing with gnome-terminal? – wjandrea – 2017-05-11T19:36:23.923

Works on Kitty (0.13.3) w/TERM=xterm-kitty, and Alacritty (0.3.3) w/TERM=xterm-256color. It doesn't seem to work under TMUX. – A.Danischewski – 2019-10-07T14:15:46.140

I suggest improving this answer so that it tells how to also set the foreground and cursor colors. Change the 11 to 10 for fg, 12 for cursor. – hackerb9 – 2019-12-09T18:53:51.897

1This is not working for me, it echos a blank line with no observable change in the terminal. – Richard – 2012-12-08T10:09:04.993

1This worked for me, whereas the others did not -- very helpful, thx – vol7ron – 2013-05-07T14:07:27.853

1+1 changes the window background, and allows color names - like "green" instead of "#00ff00". – Rob I – 2013-05-09T15:28:00.673

3

Yes. ANSI terminals support ANSI Escape Codes. Each Control Sequence Introducer(CSI) Code in the following format:

ESC[<<<CODE>>>

The Ascii character 27 (the ESC character) or 1b in hexadecimal, followed by a left square bracket, and then a letter denoting the action to be used.

Note that a list of ; separated parameters may be supplied directly before the <<<CODE>>> parameter.

Now, colors use a subset of CSI codes, the Select Graphic Rendition codes. These are in the form:

ESC[<<<SGR>>>m

The SGR code is passed as a parameter the CSI. Relevant to your question are the SGR codes 30-49. Codes 30-39 set the foreground color. Codes 40-49 set the background color.

30 - Foreground Black
31 - Foreground Red
32 - Foreground Green
33 - Foreground Yellow
34 - Foreground Blue
35 - Foreground Magenta
36 - Foreground Cyan
37 - Foreground White

40 - Background Black
41 - Background Red
42 - Background Green
43 - Background Yellow
44 - Background Blue
45 - Background Magenta
46 - Background Cyan
47 - Background White

Codes 38 and 48 are special codes. These are the ones which allow you to use RGB values. The format for these is:

ESC[38;2;<r>;<g>;<b>m (Foreground)
ESC[48;2;<r>;<g>;<b>m (Background)

Note: alternative uses include \x1b[<3 or 4>8;5;<web safe color index>m. With this usage, there is a completely different color encoding. See the link at the top of this answer for more information.

Codes 39 and 49 set the foreground and background colors to their defaults, which are defined on a terminal-by-terminal basis.

In practice, the colors 30-37 40-47 are slightly different than what their labels say they are.

0 - Black
1 - Darker Red
2 - Darker Green
3 - Dark/Yellow or Brown (varies between terminals)
4 - Dark Blue
5 - Dark Magenta
6 - Dark Cyan
7 - Light Grey

To get light colors, you use the SGI for bold, 1. Bold is a misleading name. It does not make the font bold. It actually increases the brightness of the text. With bold applied the colors become:

0 - Dark Grey
1 - Bright Red
2 - Bright Green
3 - Bright Yellow
4 - Bright Blue
5 - Bright Magenta
6 - Bright Cyan
7 - White

Notice: the last two blocks of colors' numbers are are relevant to both fore- and background (<index> + (30 or 40)).

To remove all styles (back to default/normal mode) use SGR 0.

CSI codes are not all graphical. For example, ESC[2J will clear your terminal. ESC[<y>;<x>H sets the cursor position (1-indexed). See the wikipedia article for more information.

Note: to test these, use echo -e or printf.

Élektra

Posted 2011-04-13T06:49:12.233

Reputation: 131

2

NOTE: The "^[" is the escape character, and is inserted with a CTRL-V,CTRL-[, and ^G is a bell character, inserted with CTRL-V,CTRL-G

The following block is in my .bash_profile and ensures that my xterms on this system are ALWAYS white-on-black, even after logging onto another system that may have changed my colors.

perl -e '$e=chr(27);print "${e}[37m ${e}[40m ${e}[2J ${e}[1;1H";'
export PS1='^[[37m^[]0;${HOST}: ${PWD}^G^[[40m${USER}@${HOST}:${PWD}
--> '

Mike

Posted 2011-04-13T06:49:12.233

Reputation: 21

0

Among the many ANSI CSI codes is one called SGR, or Select Graphic Rendition. This is ESC, [, parameters, m, where the parameters are one or more integers in ASCII format, separated by semicolons. The many different SGR parameters are listed on the Wikipedia page above (though it doesn't go in to full detail for all of them).

Some parameters, such as 1 (bold or increased intensity) and 31 (red text) are stand-alone, and can be used individually or combined, as in ESC[31m or ESC[1;31m to give standard red and bold red foreground text, respectively.

Others take parameters themselves, which are simply provided after the code as more semicolon-separated numbers. So, for example, ESC[38;5;219m would display foreground text in extended colour number 219, and ESC[38;2;150;100;50m would display it in the colour with RGB value 150, 100, 50. In this case, 38 is the "extended set foreground color" command, which is always follwed by a subcommand. Subcommand 2 takes three parameters, the values of red, green and blue components. Differently, subcommand 5 takes just one more value, a number from 0 to 255 specifying a color from a table the terminal is configured with.

The following shell function can be handy for using these codes:

sgr() {
    local codes=${1:-0}; shift
    for c in "$@"; do codes="$codes;$c"; done
    echo -n -e "\e[${codes}m"
}

You can use it like this:

normal=$(sgr 0)
red=$(sgr 31)
echo "Text can be $(sgr 1)made boldface$(sgr 0)" \
     " or ${red}colored red${normal}" \
     " or $(sgr 31 1)even both at the same time$(sgr)."

Note that if you give no parameters to sgr() it defaults to SGR code 0, which means to turn all attributes off, resetting the text to whatever the default is for that terminal.

cjs

Posted 2011-04-13T06:49:12.233

Reputation: 380

1

Technically those ESC[38...m and ESC[38...m can/should (depends on your source of information - the ultimate one being, I believe, https://www.itu.int/rec/T-REC-T.416-199303-I ) should use the, otherwise reserved, character : (to separate the parameter elements) so that the ; is used only between complete parameter strings - i.e. ESC[38;2;150;100;50m should be written ESC[38:2::150:100:50m...

– SlySven – 2019-01-27T20:54:22.113

... unfortunately implementations often forget the color space id between the 2 and the 150 - as no-one, that I am aware of, has ever defined what value should go in there the empty default is to be used - but it is often missed off and using only ; as a separator makes it impossible to reliably process the information in accordance with the specification. – SlySven – 2019-01-27T20:55:33.763

0

check also a project ScriptEchoColor
it is completely made in bash scripts
it has packages for ubuntu here
but these scripts can be installed on any distro if you know how to (latest can be downloaded from its git also).

you can use shortened or extended color names like:

echoc "@rRedFg@{/blue}BlueFg@{/GREEN}GreenBg"

a sample: enter image description here

Also, make it sure to take a look at xtermcontrol, for a more extensive control over the xterm on itself (not only the characters).

Aquarius Power

Posted 2011-04-13T06:49:12.233

Reputation: 545