4

I have seen several answers but they all talk about echo. How can I change the color of an output of a command in bash? For instance, I want to colorize the output of hostname command.

$ hostname 
Nameofcomputer <--- Just the output to be colored and then it returns to default color of the shell.
Sparhawk
  • 19,941
Fenomatik
  • 171
  • 1
  • 1
  • 4
  • 1
    How will your system decide what and how to colour? i.e. do you want to hard code specific colours into specific commands? e.g. hostname should always output red? – Sparhawk May 05 '17 at 00:11
  • 1
    FWIW I don't think it's a dupe, but it's certainly unclear IMO. – Sparhawk May 05 '17 at 00:11
  • @Sparhawk for example $ set-color red hostname , just want the outout of command to be in certain color and then the prompt returns to default color – Fenomatik May 05 '17 at 02:23
  • I would try writing functions that echo'd out the color-changing sequences, then ran command the-original-command "$@", then the end-color sequence. You might be able to make a set-color function that creates such functions on-demand as well. Beware commands (such as some greps) that may declare their own colors. – Jeff Schaller May 05 '17 at 02:45
  • I wrote up a partial answer, just as @JeffSchaller posted. It's basically the same strategy, but fails in some cases. – Sparhawk May 05 '17 at 02:46

3 Answers3

4

This code seems to work, thank to suggestions from @finefoot.

#!/bin/bash

case $1 in red) col=$'\e[1;31m' ;; green) col=$'\e[1;32m' ;; yellow) col=$'\e[1;33m' ;; blue) col=$'\e[1;34m' ;; magenta) col=$'\e[1;35m' ;; cyan) col=$'\e[1;36m' ;; esac

printf "%s" "${col}"

shift exec "$@"

Usage

Presuming it's called set-color, simply call it with set-color red hostname.

Explanation

  • The case block defines the colours, as per jasonwryan's answer here.
  • The script sets this colour with printf.
  • shift removes the first option fed to the script (i.e. the colour).
  • exec "$@" then executes the rest of the script.
Sparhawk
  • 19,941
  • @finefoot Sparhawk replied (in a now-deleted) comment that quoting didn't help. One difference I see in your pastebin code is exec vs eval so that would need to be considered. – Jeff Schaller Nov 27 '22 at 16:12
  • @finefoot It's been half a decade since I posted this, and I don't use bash any more, but I tested your changes and they seem to work. Thank you and edited! (FWIW on my system $'...' is fine with #!/bin/sh, but quoting $@ didn't work.) – Sparhawk Nov 27 '22 at 22:11
  • @Sparhawk Maybe your sh just links to bash and that's why it works? No idea... "$'...' is a bashism" (quote from https://wiki.ubuntu.com/DashAsBinSh) so it shouldn't work with a strictly POSIX shell I guess? Never mind. :) Again, very helpful post! Thanks for keeping it updated. – finefoot Nov 28 '22 at 00:02
  • @finefoot It does link to bash, but when run as sh, bash goes into POSIX mode. There are certainly some differences on my system though. Re-reading my previous comment I was not clear, but I meant to say that I did need #!/bin/bash for the quoting of "$@" to work. This didn't work with sh. – Sparhawk Nov 28 '22 at 00:29
3

There are programs that will already do this for you, like grc, it's a

generic colouriser, can be used to colourise logfiles, output of commands, arbitrary text.... configured via regexp's.

enter image description here

[I normally don't like to use an image of text, but I don't think StackExchange has colour fomrat options]

Or there's also source-highlight.

See Is there colorizer utility that can take command output and colorize it accordingly to pre-defined scheme? on SuperUser too

Xen2050
  • 2,354
2
tput setaf 1; hostname; tput sgr0

tput queries the terminal database for the corresponding capability. Here setaf for set ANSI colour 1 (red), sgr0 to select graphic rendition none to go back to default attributes. Instead of tput sgr0, you can also use tput op (original pair) to only reset background and foreground colour and leave other graphic attributes (bold, underline, standout, reverse...) alone.

Some shells like zsh, tcsh or fish have builtin support to query that database or map color names to ANSI codes (like zsh or fish), but not bash.

In zsh, using prompt expansion to print the hostname in red:

print -P '%F{red}%m%f'

(%f only resets the foreground colour)

In tcsh or zsh with the echotc builtin using termcap codes instead of terminfo:

echotc AF 1; hostname; echotc me

(zsh has echoti for the terminfo codes setab/sgr0 like modern versions of tput).

In zsh, the % parameter expansion flag turns on prompt expansion upon parameter expansion, so you can do:

red=%F{red} normal=%f

echo ${(%)red}whatever%{(%)normal}

In zsh, you'll also find a colors autoloadable function that you can run to have helpers to write things in colour:

autoload colors; colors

echo $fg[red]whatever$fg[default]