0

I've got a simple code setup, but for whatever reason it refuses to operate how it should

#!/bin/bash
RED='\033[0:31m'
RESET='\033[0m'

Basically these are some simple color encodings

Next thing I have is

for file in ./dir/*.c; do
echo "File [${RED}$file${RESET}] has been launched"

My expected result would be

File [myprogram.c] has been launched (while the name would be in red color)

Instead it just refuses to encode the color and dumps

File [\033[0:31m] has been launched

Any idea what I'm doing wrong?

2
  • use echo -e instead of echo, also use \033[0;31m, not colon. Commented Dec 5, 2016 at 1:16
  • 1
    Don't use echo to print escape sequences. As there is no portable way to do it. Use printf instead. Commented Dec 5, 2016 at 1:16

3 Answers 3

4

First because red is '\033[31m'. What you wrote means something else, read below.
Then, because the codes need to be interpreted.
This won't work:

$ red='\033[31m'

$ echo "${red}Hello"

But this would:

$ red='\033[31m'

$ echo -e "${red}Hello"

Or, you can assign the interpreted values to a variable:

$ red="$(echo -e '\033[31m')"
$ red="$(printf '\033[31m')"

Then the escapes don't need to be interpreted:

$ echo "${red}Hello"

What you wrote (besides using a colon where a semicolon should be) was setting the "boldness" of the foreground, or 0 for thin/light and 1 for bold/bright.

$ printf '\033[31mHello\033[0;31mHello\033[1;31mHello'

Also, 3x is for foreground 4x is for background:

$ printf '\033[31;42mHello\033[0;44;31mHello\033[1;43;31mHello\033[0m'

A full table could be printed with this:

$ printf "$(printf '%s' 033[{0,1}';'3{1..8}{';'4{1..8}mXXX,';'40m=OoO\\033[0m\\n}  )"

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

You should really use tput to get color codes for the shell.
@andlrc Why? Doesn't the code I wrote work in your system?
1

With tput

#!/bin/bash
red=$(tput setaf 1)
reset=$(tput sgr0)
for file in ./dir/*.c; do
 echo "File [${red}$file${reset}] has been launched"
done

with printf

#!/bin/bash
RED='\033[0;31m'
RESET='\033[0m'
for file in ./dir/*.c; do
 printf  "File [${RED}$file${RESET}] has been launched"
done

Comments

0

There is a typo in your code. Red color code is [031m. The ASCII codes always start with an escape character, octal 33: \033. Thus, to start printing red text join the two sequences: \033[031m.

I find this post very helpful. In particular, the author recommends to use tput instead of the hard-coded values, and I agree with him.

Example

die() {
    local message="$1"
    : ${message:=Aborted}

    # See info bash BASH_SOURCE, info bash FUNCNAME, info bash BASH_LINENO
    printf '%s at %s:%s line %d\n' \
      "$message" ${BASH_SOURCE[1]} ${FUNCNAME[1]} ${BASH_LINENO[0]} >&2

    exit 1
}

# See man 1 tput, man 5 terminfo.
red=$(tput setaf 1) || die
noattr=$(tput sgr0) || die

# If tput is unavailable (very unlikely), use the hardcoded values as follows.
# The ANSI codes always start with the escape character (octal 33).
#esc='\033'
#red="${esc}[031m"
#noattr="${esc}[0m"

# %b causes printf to expand backslash escape sequences. See info bash printf.
printf '%b%s%b\n%s\n' "$red" 'red text' "$noattr" 'normal text'

Note the use of printf. Don't use echo in new software.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.