I'm trying to get the number of columns or lines of my terminal but the variables COLUMNS / LINES are always empty.

COLUMNS and LINES are set by BASH in interactive mode; they are not available by default in a script. On most systems, you can try to query the terminal yourself:

unsup() { echo "Your system doesn't support retrieving $1 with tput.  Giving up." >&2; exit 1; }
COLUMNS=$(tput cols) || unsup cols
LINES=$(tput lines) || unsup lines

Bash automatically updates the COLUMNS and LINES variables when an interactive shell is resized. If you're setting the variables in a script and you want them to be updated when the terminal is resized, i.e. upon receipt of a SIGWINCH, you can set a trap yourself:

trap 'COLUMNS=$(tput cols) LINES=$(tput lines)' WINCH

You can also set the shell as interactive in the script's shebang:

#!/bin/bash -i
echo $COLUMNS

This has some drawbacks, however:

Though you can technically set -i in the middle of a script, it has no effect on the setting of COLUMNS and LINES. -i must be set when Bash is first invoked.

Normally Bash updates COLUMNS and LINES when your terminal sends a SIGWINCH signal, indicating a change of size. Some terminals may not do this, so if your variables aren't being updated even when running an interactive shell, try using the shopt -s checkwinsize. This will make Bash query the terminal after every command, so only use it if it's really necessary.

tput, of course, requires a terminal. According to POSIX, if stdout is not a tty, the results are unspecified, and stdin is unused, though some implementations may try using it anyway. On OpenBSD and Gentoo, and Debian Linux (and apparently at least some other Linuxes), at least one of stdout or stderr must be a tty, or else tput just returns some default values:

linux$ tput -S <<<$'cols\nlines' 2>&1 | cat
80
24

openbsd$ tput cols lines 2>&1 | cat
80
24

BashFAQ/091 (last edited 2016-10-22 17:32:20 by tor-2)