Skip to main content
ansicode
Bash / shell

ANSI escape codes in Bash / shell

Bash has two reliable ways to emit escape bytes: `printf` with `\033` / `\x1b` (POSIX-portable), and `tput` (terminfo-driven, the safest because it adapts to `$TERM`). `echo -e` works in bash but breaks in dash / sh; avoid it in portable scripts. The literal `$'\e[...'` ANSI-C quoting form is bash/zsh-only but very readable.

Recommended libraries

  • tput

    ncurses-bundled binary: `tput setaf 1` emits red foreground escape for the current `$TERM`. Use this in scripts that need to work on dumb / 16-colour / 256-colour terminals alike.

  • gum (charmbracelet)

    Pre-styled shell primitives — `gum style`, `gum spin`, `gum choose`, `gum confirm`. Wraps lipgloss / bubbletea for shell scripts.

  • dialog / whiptail

    Classic full-screen menus / inputs / progress over curses. `whiptail` is the lighter, BSD-licensed clone shipped with Debian.

  • ncurses

    C library, but bash scripts can call helper binaries like `clear`, `reset`, `tput`, `infocmp` that ship with it.

Idiomatic patterns

printf with octal — the portable form
printf '\033[1;31m%s\033[0m %s\n' 'error:' 'permission denied'
Named tput colours — terminfo-aware
RED=$(tput setaf 1)
BOLD=$(tput bold)
RESET=$(tput sgr0)

printf '%s%serror:%s permission denied\n' "$BOLD" "$RED" "$RESET"
Bash ANSI-C quoting ($'...') — readable
red=$'\e[31m'
reset=$'\e[0m'
echo "${red}error${reset}: permission denied"
Respect NO_COLOR
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
  RED=$'\e[31m'; RESET=$'\e[0m'
else
  RED=""; RESET=""
fi
printf '%serror:%s permission denied\n' "$RED" "$RESET"

Related sequences

Other languages