8

I know this is something simple, but I can't recall where it's located/named.

Where's the variable for the current width of the terminal stored?

I see this answer talks about changing things: How are terminal length and width forwarded over SSH and telnet?

But I'd like to get the current value, for use in a script (and I don't understand everything in that answer).

Once upon a time I recall there was some way to display all environment variables? (Hmm, I see an answer that says use set (vs. env), but my set only shows LINES and not width?)


Then of course it's onto the next problem; once I have that $number I'd like to repeat a character ( "-" ) that many times, to make a dashed line that's X-characters-wide (fills the terminal, without wrapping). If you've got an elegant way I should be doing that, I'd appreciate that too.

user3082
  • 991
  • 2
  • 10
  • 18
  • 1
    $COLUMNS is one such variable. Also there's stty -a or more specifically stty size. – slm Jul 13 '15 at 05:41
  • 1
    btw: To display all environment variables in your shell use env. – ikrabbe Jul 13 '15 at 05:48
  • FWIW, some utilities that predate the environment variables may require a command-line argument. For instance diff -W ${COLUMNS} -y wideFiles* – Mark Hudson Dec 07 '20 at 22:23

4 Answers4

11

STTY SIZE

The canonical way is to ask the terminal about its actual size, when you want to know it

stty size

prints ROWS COLUMNS.

Print a dashed line

About your second question, seq is your friend

stty size|if read rows cols
then for x in `seq $cols`
do printf "-"
done fi

or per awk loop

stty size|awk '{ ORS="-"; n=$2; for (i=0; i<n; ++i) { print ""; } }'

.

Set a line variable

But actually it would be better to save our line in a variable

eval $(L=""; stty size|if read r c
    then for x in `seq $c`
    do L="${L}-"
    done
    echo L="$L"
    fi
)

Trap on SIGWINCH

As long as we don't need to recalculate the terminal size

trap 'echo "recalculate L"' SIGWINCH

we can now use $L to print the line. Of course you can autotune your $L variable on SIGWINCH:

trap 'eval $(L=""; stty size|if read r c
    then for x in `seq $c`
    do L="${L}-"
    done
    echo L="$L"
    fi
)' SIGWINCH

. In a terminal where you set up, such a trap you can just say

echo $L

and you are done.

ikrabbe
  • 2,163
4

There is no environment variable that contains the terminal width. There is a shell variable: COLUMNS (and likewise LINES for the height). This is only a shell variable, it is not visible to programs invoked by the shell.

The reason COLUMNS is only a shell variable and not exported into the environment is that once the variable is in the environment, the shell can't modify it. If you resize the terminal, the shell (or more generally any program in the foreground) receives a SIGWINCH signal. When the shell receives a SIGWINCH, it queries the terminal for its current size and updates the COLUMNS and LINES variables accordingly.

The command set lists all shell variables, so that includes COLUMNS and LINES. The commands env and export list only environment variables, so that doesn't include COLUMNS and LINES.

You can export COLUMNS to make it an environment variable. But note that by the time an application uses it, the information may be obsolete, if the terminal has been resized in the meantime. An application can query the terminal size in the same way the terminal does¹, and register a handler for the SIGWINCH signal so that it can keep the information up to date.

¹ By sending the right ioctl commands. Or even by calling stty size or tput cols.

1

I believe you may be looking for the $COLUMNS variable.

As for making a character span the entire width of the terminal, that's a simple loop based on the value of $COLUMNS. If the screen is resized with those line in the history they will look quite unpleasant.

muru
  • 72,889
Jason
  • 191
  • 2
    That's not actually an environment variable, it's a virtual invention of [some] shells. The proof is that if it were an environment variable, it would not change when your tty was resized. – Celada Jul 13 '15 at 05:45
1

It's in set under COLUMNS.

echo $COLUMNS

or

set | grep -i columns

in bash.

cremefraiche
  • 555
  • 3
  • 9
  • 6
    That's not actually an environment variable, it's a virtual invention of [some] shells. The proof is that if it were an environment variable, it would not change when your tty was resized. – Celada Jul 13 '15 at 05:46
  • @Celada Here is a quote from, A Practical Guide to Fedora and RHEL Seventh Edidtion, although this stands in debian as well. "The set builtin can perform the following tasks.... -Display variables that are available to the current shell. These variables comprise shell variables (variables not in the environment) and environment variables." (pp.1036). OP already said they are using set, so bash is assumed. – cremefraiche Jul 13 '15 at 06:07
  • 5
    I realize that, but I felt it was necessary to stress the fact that $COLUMNS is not actually an environment variable, because it looked like the OP was expecting it to be one. It turns out the OP did indeed expect it to be one and ran into further problems because of that assumption.. – Celada Jul 13 '15 at 06:44