5

In my script I have somewhat following lines:

str=$(command) 

Then I want to echo output of a command using red color:

echo -e "\e[31m$str\e[0m"  

But it continues to print it in default color.
Found interesting thing: when I add --color to the end of my command it DOES print command output in red color, but it says following:

Invalid command line options. Usage:
kes4lwks-control [-L] --show-license-info <file>

Is there any chance to print output of that command in color?
If you need, I'm executing next command:

/opt/kaspersky/kes4lwks/bin/kes4lwks-control --show-license-info <path-to-lic-file>

UPDATE:
My above code perfectly works, when command executes with out errors (returns 0), but when it says, for example,

Error, couldn't show infromation on the license: signature of license key is invalid.

Echoed text is not colored. May be I need something to do with stderr descriptor?

5
  • 2
    your code as posted works for me. Using GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu) Commented Aug 24, 2015 at 9:38
  • Works on Ubuntu, doesn't work on OSX. Replacing \e with \033 makes it work. Commented Aug 24, 2015 at 9:39
  • 1
    However that only works on certain terminals (ubiquitous now, but still). echo "$(tput setaf 1)$str$(tput setaf 0)" should work anywhere (as long as terminal has colour support). Commented Aug 24, 2015 at 9:43
  • I'm using GNU bash, version 4.2.20(1)-release (x86_64-pc-linux-gnu) Commented Aug 24, 2015 at 9:45
  • Unfortunately, it doesn't work even with tput :( After using tput my next echo command echo -e "\e[1mEnter path to key-file:\e[0m" prints text colored in Gray, instead of Bold style. Commented Aug 24, 2015 at 9:57

1 Answer 1

4

You are confusing yourself by not distinguishing between normal program output to stdout and error messages output to stderr.

Executing

str=$(command)

causes command to be executed with its stdout redirected, but without changing stderr. The consequence is that error messages sent to stderr will just appear immediately on stderr, which is presumably still your terminal.

The redirection is to a bash process which captures the output (that is, to stdout) and, when the command is finished, assigns the collected output to the shell variable. If there was an error and nothing was sent to stdout, the shell variable will end up set to an empty string.

So

str=$(command)
printf '\033[31m%s\033[0m\n' "$str"

will directly output error messages, and will capture and later output regular output. (I changed the echo to printf and \e to \033 in order to make the command portable. Also see note 1, below.)

If you just want to colour output, there is no need to capture the output in a variable at all. Just send the appropriate colour sequences before and after executing the command:

printf '\033[31m'
command
printf '\033[0m'

That will colour all output from command. (Of course, the output itself could include colour sequences, but there is no simple way to get around that.)

If you have some other reason to capture the output (which seems unlikely), you could run the command with stderr redirected to stdout. In that case, you will get both stdout and stderr output (intermingled) in the shell variable:

str=$(command 2>&1)

Notes

  1. Although using ANSI colour sequences is probably going to work in any modern platform on which bash is running, some people will recommend the use of the tput command in order to access the terminfo database. For example,

    tput setaf 1   # Set terminal to ANSI colour 1 (red)
    command
    tput sgr0      # Reset all terminal attributes
    

    tput setaf 0 is not the same as the control sequence ESC [ 0 m. setaf 0 sets the foreground colour to black, which will make output invisible if you use a white-on-black console, while ESC [ 0 m resets all character display attributes to their defaults. That's also what tput sgr0 is defined as doing, although it may also reset other terminal attributes. (With my terminfo setting, tput sgr0 outputs ESC ( B followed by ESC [ m; the former resets the terminal font mapping, which I think is redundant in my case. But YMMV.)

    It is possible (but unlikely) that there is no setaf entry for your terminal, in which case you are supposed to fall back to setf; however, the colour numbering is different so that setf 1 is blue and setf 4 is red, while setaf 1 is red and setaf 4 is blue. All of these convoluted details are documented in man 5 terminfo. Search for "Color Handling" and enjoy. If you are using Linux, you might also find man 4 console_codes interesting reading.

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

2 Comments

Thank you very much, rici, for such informative and detailed answer. You helped me a lot to understood, what was going on. My only goal was to color error output in red and successful executions - in green.
@Zeolite: you could have asked that directly :) I'd do that by outputting the red console code, then grabbing the stdout of the command into a variable (letting stderr get printed directly to the terminal), then outputting the green console code, then finally printf'ing the captured stdout from the variable, and outputting an attribute reset code. Of course, that assumes that the command will terminate quickly and not produce too much on stdout; otherwise, delaying the output is not ideal as a user experience.

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.