Adding colors to Bash scripts
Ifenna

Ifenna @ifenna__

Joined:
May 31, 2018

Adding colors to Bash scripts

Publish Date: Nov 23 '19
222 16

I recently wrote a post-receive git hook for a server and I wanted to easily distinguish my hook's output from git information. This led me to look into colorizing bash output.

By using ANSI color escape codes, we can add color to output strings. The ANSI standard specifies certain color codes;

Color Foreground Code Background Code
Black 30 40
Red 31 41
Green 32 42
Yellow 33 43
Blue 34 44
Magenta 35 45
Cyan 36 46
Light Gray 37 47
Gray 90 100
Light Red 91 101
Light Green 92 102
Light Yellow 93 103
Light Blue 94 104
Light Magenta 95 105
Light Cyan 96 106
White 97 107

To change the color of the text, what we want is the foreground code. There are also a few other non-color special codes that are relevant to us:

Code Description
0 Reset/Normal
1 Bold text
2 Faint text
3 Italics
4 Underlined text

The echo command prints out text. We need to tell it that we're working with special ANSI codes, not just regular characters. This can be accomplished by adding a \e at the beginning to form an escape sequence. The escape sequence for specifying color codes is \e[COLORm (COLOR represents our color code in this case). By default, echo does not support escape sequences. We need to add the -e option to enable their interpretation.

To print red text, therefore, we could have



echo -e "\e[32mRed text\e[0m"


Enter fullscreen mode Exit fullscreen mode

The \e[0m means we use the special code 0 to reset text color back to normal. Without this, all other text you print out after this would be red.

This works, but it would be more readable if we store the color codes in variables and use those instead.



RED="\e[31m"
ENDCOLOR="\e[0m"

echo -e "${RED}Red text${ENDCOLOR}"


Enter fullscreen mode Exit fullscreen mode

Putting all these together, we could have a script like this



#! /usr/bin/env bash

RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"

echo -e "${RED}This is some red text, ${ENDCOLOR}"
echo -e "${GREEN}And this is some green text${ENDCOLOR}"


Enter fullscreen mode Exit fullscreen mode

Demoing this

We can combine escape codes to get more fancy output.



#! /usr/bin/env bash

RED="31"
GREEN="32"
BOLDGREEN="\e[1;${GREEN}m"
ITALICRED="\e[3;${RED}m"
ENDCOLOR="\e[0m"

echo -e "${BOLDGREEN}Behold! Bold, green text.${ENDCOLOR}"
echo -e "${ITALICRED}Italian italics${ENDCOLOR}"


Enter fullscreen mode Exit fullscreen mode

Another one

You can use these in any number of ways to make your scripts less monotonous. The combinations are up to you. Happy scripting!

Comments 16 total

  • Ben Sinclair
    Ben SinclairNov 23, 2019

    Using escape codes directly is cool, but I'm a fan of using tput like this:

    # SET Attribute Foreground <colour 123>
    kindalightblue=$(tput setaf 123)
    
    Enter fullscreen mode Exit fullscreen mode

    There are a lot of handy things tput can do, and though the capabilities vary with your terminal, and though it's not completely portable either, you get all the colours your terminal can show.

    • Ifenna
      IfennaNov 23, 2019

      I haven't heard about tput before. I'll definitely check it out.

      EDIT: Just took a look. It's great. Thanks for the tip 🚀.

  • Johnny Bell
    Johnny BellNov 23, 2019

    Great article. Something that should be simple but is actually super hard to understand thank you

    • Ifenna
      IfennaNov 23, 2019

      Glad to help.

  • Diego Torres Milano
    Diego Torres MilanoNov 26, 2019

    If you want to see the colors you can use this script: gist.github.com/dtmilano/4055d6df5... which uses tput.

  • Ifenna
    IfennaFeb 8, 2020

    Thanks for noticing! Fixed it.

  • Placid Rodrigues
    Placid RodriguesMay 22, 2020

    Thank you for the super helpful post.
    I think the first example should be: echo -e "\e[31mRed text\e[0m"
    32 represents green.

  • jianwu
    jianwuJul 27, 2021

    Thanks for the great article. However in my environment, if I run the example, it will print the escape code literally. e.g.

    $ echo -e "\e[32mRed text\e[0m"
    \e[32mRed text\e[0m
    
    Enter fullscreen mode Exit fullscreen mode

    For me the solution is to use printf, e.g.

    echo -e $(printf "\e[32mRed text\e[0m")`
    
    Enter fullscreen mode Exit fullscreen mode
    • Ariel Bogdziewicz
      Ariel BogdziewiczJul 7, 2022

      This helped me as well in macOS. Thank you!

    • Sombody101
      Sombody101Aug 27, 2022

      Try using -ne rather than -e.

    • Toran Sahu
      Toran SahuOct 17, 2022

      Try $ echo -e "\033[32mRed text\e[0m"
      \e[32mRed text\033[0m
      . i.e. \033 instead \e.

  • kuberdenis
    kuberdenisNov 30, 2021

    Great post!

  • Keith
    KeithMar 24, 2023
    bgreen () { printf "\e[1m\e[32m" ; $@ ; printf "\e[0m"; }
    red    () { printf      "\e[31m" ; $@ ; printf "\e[0m"; }
    
    bgreen echo "Am I green?"
    
    Enter fullscreen mode Exit fullscreen mode
  • Kliment Ognianov
    Kliment OgnianovFeb 16, 2024

    Just add '5' as a blinking special, non-colour code ;)

  • laakkus
    laakkusMar 15, 2024

    I have RED already in use, so had to do this:

        NORMAL=0
        BOLD=1
        FAINT=2
        ITALIC=3
        UNDERLINE=4
        RED='\033[0;31m'
        ITALICRED=$(echo $RED|sed -e "s/\[./\[${ITALIC}/")
        FAINTRED=$(echo $RED|sed -e "s/\[./\[${FAINT}/")
    
    Enter fullscreen mode Exit fullscreen mode
Add comment