13

Does something like this exist in Unix?

$ echo "this should show in red" | red
$ echo "this should show in green" | green
$ echo "this should show in blue" | blue

Here I don't mean for literal color code text to come up (to be pasted in a file, for example). I just mean for the text to actually show up in the terminal as that color. Is this possible?

14

Here's a little script that does just that. Save this as color in a directory in your $PATH (for example, ~/bin if that's in your $PATH):

#!/usr/bin/env perl

use strict;
use warnings;
use Term::ANSIColor; 

my $color=shift;
while (<>) {
    print color("$color").$_.color("reset");
} 

Then, pass your text through the script, giving . as the pattern to match and specifying a color:

screenshot of a terminal running the script

The supported colors depend on the abilities of your terminal. For more details, see the documentation of the Term::ANSIColor package.

23

You'd use tput for that:

tput setaf 1
echo This is red
tput sgr0
echo This is back to normal

This can be used to build a pipe:

red() { tput setaf 1; cat; tput sgr0; }
echo This is red | red

The basic colours are respectively black (0), red (1), green, yellow, blue, magenta, cyan and white (7). You'll find all the details in the terminfo(5) manpage.

6

With zsh:

autoload colors; colors
for color (${(k)fg})
  eval "$color() {print -n \$fg[$color]; cat; print -n \$reset_color}"

And then:

$ echo "while" | blue
while
1

(as discussed in comments, use tput instead if you have it)

Using bourne shell and echo (built-in) command which understands the ANSI escape \e with -e option:

black()  { IFS= ; while read -r line; do echo -e '\e[30m'$line'\e[0m'; done; }
red()    { IFS= ; while read -r line; do echo -e '\e[31m'$line'\e[0m'; done; }
green()  { IFS= ; while read -r line; do echo -e '\e[32m'$line'\e[0m'; done; }
yellow() { IFS= ; while read -r line; do echo -e '\e[33m'$line'\e[0m'; done; }
blue()   { IFS= ; while read -r line; do echo -e '\e[34m'$line'\e[0m'; done; }
purple() { IFS= ; while read -r line; do echo -e '\e[35m'$line'\e[0m'; done; }
cyan()   { IFS= ; while read -r line; do echo -e '\e[36m'$line'\e[0m'; done; }
white()  { IFS= ; while read -r line; do echo -e '\e[37m'$line'\e[0m'; done; }

echo '    foo\n    bar' | red

or, more generic shell script (say, /usr/local/bin/colorize):

#!/bin/sh

usage() {
    echo 'usage:' >&2
    echo '  some-command | colorize {black, red, green, yellow, blue, purple, cyan, white}' >&2
    exit 1
}

[ -z "$1" ] && usage

case $1 in
    black)  color='\e[30m' ;;
    red)    color='\e[31m' ;;
    green)  color='\e[32m' ;;
    yellow) color='\e[33m' ;;
    blue)   color='\e[34m' ;;
    purple) color='\e[35m' ;;
    cyan)   color='\e[36m' ;;
    white)  color='\e[36m' ;;
    *) usage ;;
esac

IFS=
while read -r line; do
    echo -e $color$line'\e[0m'
done

IFS= is needed to prevent whitespace trimming (see POSIX for details).

how IFS works

  • I advise to prefer using tput. – LinuxSecurityFreak Aug 1 at 11:55
  • This is completely non-portable solution. I mean you should adhere to POSIX. – LinuxSecurityFreak Aug 1 at 11:58
  • 1
    Sure, if we could. It's intended to be used on embedded systems or rescue environments like busybox. I decided to write this answer because I believe these code snippets are useful in some situations -- at least for busybox users and for me, who had to output colors only with shell's built-in commands on an embedded environment today. – wataash Aug 1 at 12:21
  • forgot to say that ordinary busybox doesn't have tput. – wataash Aug 1 at 12:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.