Skip to content
shellhacks.dev
Bash

Draw a Full-Width Horizontal Rule in a Bash Terminal

Draw a rule as wide as the terminal with printf and a star width plus tr, or build it with a parameter expansion. COLUMNS is only set in an interactive Bash.

1 min read
Summarize in AI

A script prints sections and you want a divider line that spans the terminal, or any other fixed width.

Shell
cols=${COLUMNS:-$(tput cols 2>/dev/null || echo 40)}
printf '%*s\n' "$cols" '' | tr ' ' '-'
printf -v line '%*s' 20 ''
echo "${line// /=}"
printf '%*s%s\n' 5 '' 'indented by five'
Text
----------------------------------------
====================
     indented by five

printf '%*s' N '' prints N spaces, because the star takes its width from the argument list, and tr ' ' '-' turns each space into a dash. The second form keeps the spaces in a variable and replaces them with ${line// /=}, which needs no external command. COLUMNS holds the terminal width in an interactive shell, and tput cols asks the terminal otherwise. The format string is described under the printf builtin.

COLUMNS is not exported and is unset in scripts, and tput cols fails without a terminal, so the example falls back to 40 columns, as it did in this run. A rule made of multibyte characters needs the parameter-expansion form, because GNU tr works on bytes.

Share

More snippets

Bash

Reverse a String in Pure Bash Without rev

Reverse a string in pure Bash with a for loop and substring expansion. It handles UTF-8, but it took about 2 seconds for 20000 characters where rev took 2 milliseconds.

1 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.