There are several aspects at play in what you're asking.
First, bash doesn't define colors. In fact bash has absolutely no idea that colors even exist. All it knows is that you told it to output the characters \033[0;36m
. Your terminal emulator (xterm, gnome-terminal, whatever) receives these characters and understands "I need to start outputting in cyan".
Thus it is your terminal emulator that understands colors. Your terminal emulator understands that \033[0;36m
is cyan, but another terminal emulator might use an entirely different set of characters for cyan (though no sane terminal emulator would flaunt the standard and do this). This is the reason for tput
. When you run tput setaf 6
, tput
is going to look up your terminal's escape codes for the color 6 (cyan), and output that escape code.
(see this question for more info on tput setaf
codes)
Now back to bash. As you may have noticed, when I've been referring to the cyan color, I've been using \033[0;36m
, not \[\033[0;36m\]
. The square brackets have been missing. The purpose of the square brackets is that when using escape codes (colors) in the prompt, bash has to know which characters are non-printing (zero-width, don't actually show anything). Thus you enclose non-printing characters in \[
\]
. If you remove these characters, everything might appear to work just fine at first, but you'll start running into all sorts of weirdness when your command exceeds the terminal width. This is because when typing, bash has to know when the command should wrap to the next line. To do this, it calculates the width of the prompt, and then the width of how much you've typed.
Another note, about tput
. CYAN="\[\033[0;36m\]"
is not the same thing as CYAN="$(tput setaf 6)"
. As we just discussed, the square brackets are relevant to bash, and tput
is only going to output the terminal escape codes.
Since square brackets are usually only relevant in the prompt, if you're using colors in the output of a script or something, you should not use them. Meaning that if you're going to be using colors for more than prompts, you need to define multiple variables. One with square brackets for using in the prompt, and one without for everything else. Though you could just manually add the square brackets every time you reference a color in the prompt.
So long story short, you probably want to define something like:
local CYAN="$(tput setaf 6)" # OR CYAN="\033[0;36m"
local LIGHT_CYAN="$CYAN$(tput bold)" # OR LIGHT_CYAN="\033[1;36m"
local PROMPT_CYAN="\[$CYAN\]"
local PROMPT_LIGHT_CYAN="\[$LIGHT_CYAN\]"
\e[1;30m
, for example, doesn't technically represent gray, but rather the color slot usually displayed as gray by a terminal. Terminal emulators are free to change the actual display colors, and often make them a user-configurable option. – chepner Sep 30 '14 at 13:09