Using colors with printf

LinuxBashColorsPrintf

Linux Problem Overview


When written like this, it outputs text in blue:

printf "\e[1;34mThis is a blue text.\e[0m"

But I want to have format defined in printf:

printf '%-6s' "This is text"

Now I have tried several options how to add color, with no success:

printf '%-6s' "\e[1;34mThis is text\e[0m"

I even tried to add attribute code to format with no success. This does not work and I can't find anywhere an example, where colors are added to printf, which has defined format as in my case.

Linux Solutions


Solution 1 - Linux

Rather than using archaic terminal codes, may I suggest the following alternative. Not only does it provide more readable code, but it also allows you to keep the color information separate from the format specifiers just as you originally intended.

blue=$(tput setaf 4)
normal=$(tput sgr0)

printf "%40s\n" "${blue}This text is blue${normal}"

See my answer HERE for additional colors

Solution 2 - Linux

You're mixing the parts together instead of separating them cleanly.

printf '\e[1;34m%-6s\e[m' "This is text"

Basically, put the fixed stuff in the format and the variable stuff in the parameters.

Solution 3 - Linux

This works for me:

printf "%b" "\e[1;34mThis is a blue text.\e[0m"

From printf(1): > %b ARGUMENT as a string with '' escapes interpreted, except that octal > escapes are of the form \0 or \0NNN

Solution 4 - Linux

This is a small program to get different color on terminal.

#include <stdio.h>

#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KYEL  "\x1B[33m"
#define KBLU  "\x1B[34m"
#define KMAG  "\x1B[35m"
#define KCYN  "\x1B[36m"
#define KWHT  "\x1B[37m"

int main()
{
    printf("%sred\n", KRED);
    printf("%sgreen\n", KGRN);
    printf("%syellow\n", KYEL);
    printf("%sblue\n", KBLU);
    printf("%smagenta\n", KMAG);
    printf("%scyan\n", KCYN);
    printf("%swhite\n", KWHT);
    printf("%snormal\n", KNRM);

    return 0;
}

Solution 5 - Linux

This is a little function that prints colored text using bash scripting. You may add as many styles as you want, and even print tabs and new lines:

#!/bin/bash

# prints colored text
print_style () {

    if [ "$2" == "info" ] ; then
        COLOR="96m";
    elif [ "$2" == "success" ] ; then
        COLOR="92m";
    elif [ "$2" == "warning" ] ; then
        COLOR="93m";
    elif [ "$2" == "danger" ] ; then
        COLOR="91m";
    else #default color
        COLOR="0m";
    fi

    STARTCOLOR="\e[$COLOR";
    ENDCOLOR="\e[0m";

    printf "$STARTCOLOR%b$ENDCOLOR" "$1";
}

print_style "This is a green text " "success";
print_style "This is a yellow text " "warning";
print_style "This is a light blue with a \t tab " "info";
print_style "This is a red text with a \n new line " "danger";
print_style "This has no color";

Solution 6 - Linux

I use this c code for printing coloured shell output. The code is based on this post.

//General Formatting
#define	GEN_FORMAT_RESET				"0"
#define	GEN_FORMAT_BRIGHT				"1"
#define	GEN_FORMAT_DIM					"2"
#define	GEN_FORMAT_UNDERSCORE			"3"
#define	GEN_FORMAT_BLINK				"4"
#define	GEN_FORMAT_REVERSE				"5"
#define	GEN_FORMAT_HIDDEN				"6"

//Foreground Colors
#define	FOREGROUND_COL_BLACK			"30"
#define	FOREGROUND_COL_RED				"31"
#define	FOREGROUND_COL_GREEN			"32"
#define	FOREGROUND_COL_YELLOW			"33"
#define	FOREGROUND_COL_BLUE				"34"
#define	FOREGROUND_COL_MAGENTA			"35"
#define	FOREGROUND_COL_CYAN				"36"
#define	FOREGROUND_COL_WHITE			"37"

//Background Colors
#define	BACKGROUND_COL_BLACK			"40"
#define	BACKGROUND_COL_RED				"41"
#define	BACKGROUND_COL_GREEN			"42"
#define	BACKGROUND_COL_YELLOW			"43"
#define	BACKGROUND_COL_BLUE				"44"
#define	BACKGROUND_COL_MAGENTA			"45"
#define	BACKGROUND_COL_CYAN				"46"
#define	BACKGROUND_COL_WHITE			"47"

#define SHELL_COLOR_ESCAPE_SEQ(X) "\x1b["X"m"
#define SHELL_FORMAT_RESET	ANSI_COLOR_ESCAPE_SEQ(GEN_FORMAT_RESET)

int main(int argc, char* argv[])
{
    //The long way
    fputs(SHELL_COLOR_ESCAPE_SEQ(GEN_FORMAT_DIM";"FOREGROUND_COL_YELLOW), stdout);
    fputs("Text in gold\n", stdout);
    fputs(SHELL_FORMAT_RESET, stdout);
    fputs("Text in default color\n", stdout);
    
    //The short way
    fputs(SHELL_COLOR_ESCAPE_SEQ(GEN_FORMAT_DIM";"FOREGROUND_COL_YELLOW)"Text in gold\n"SHELL_FORMAT_RESET"Text in default color\n", stdout);

    return 0;
}

Solution 7 - Linux

man printf.1 has a note at the bottom: "...your shell may have its own version of printf...". This question is tagged for bash, but if at all possible, I try to write scripts portable to any shell. dash is usually a good minimum baseline for portability - so the answer here works in bash, dash, & zsh. If a script works in those 3, it's most likely portable to just about anywhere.

The latest implementation of printf in dash[1] doesn't colorize output given a %s format specifier with an ANSI escape character \e -- but, a format specifier %b combined with octal \033 (equivalent to an ASCII ESC) will get the job done. Please comment for any outliers, but AFAIK, all shells have implemented printf to use the ASCII octal subset at a bare minimum.

To the title of the question "Using colors with printf", the most portable way to set formatting is to combine the %b format specifier for printf (as referenced in an earlier answer from @Vlad) with an octal escape \033.


portable-color.sh

#/bin/sh
P="\033["
BLUE=34
printf "-> This is %s %-6s %s text \n" $P"1;"$BLUE"m" "blue" $P"0m"
printf "-> This is %b %-6s %b text \n" $P"1;"$BLUE"m" "blue" $P"0m"

Outputs:

$ ./portable-color.sh
-> This is \033[1;34m blue   \033[0m text
-> This is  blue    text

...and 'blue' is blue in the second line.

The %-6s format specifier from the OP is in the middle of the format string between the opening & closing control character sequences.


[1] Ref: man dash Section "Builtins" :: "printf" :: "Format"

Solution 8 - Linux

#include <stdio.h>

//fonts color
#define	FBLACK		"\033[30;"
#define	FRED		"\033[31;"
#define	FGREEN		"\033[32;"
#define	FYELLOW		"\033[33;"
#define	FBLUE		"\033[34;"
#define	FPURPLE		"\033[35;"
#define	D_FGREEN	"\033[6;"
#define FWHITE		"\033[7;"
#define	FCYAN		"\x1b[36m"

//background color
#define	BBLACK		"40m"
#define	BRED		"41m"
#define	BGREEN		"42m"
#define	BYELLOW		"43m"
#define	BBLUE		"44m"
#define	BPURPLE		"45m"
#define	D_BGREEN	"46m"
#define	BWHITE		"47m"

//end color
#define	NONE		"\033[0m"

int main(int argc, char *argv[])
{
	printf(D_FGREEN BBLUE"Change color!\n"NONE);
	
	return 0;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJernej JerinView Question on Stackoverflow
Solution 1 - LinuxSiegeXView Answer on Stackoverflow
Solution 2 - LinuxgeekosaurView Answer on Stackoverflow
Solution 3 - LinuxVladView Answer on Stackoverflow
Solution 4 - LinuxKritpal SinghView Answer on Stackoverflow
Solution 5 - LinuxArian AcostaView Answer on Stackoverflow
Solution 6 - LinuxJonny SchubertView Answer on Stackoverflow
Solution 7 - LinuxAaronDanielsonView Answer on Stackoverflow
Solution 8 - LinuxThlvView Answer on Stackoverflow