You can use ANSI escape sequences for cursor movement, most notably:
- Position the Cursor:
\033[<L>;<C>H
, or \033[<L>;<C>f
puts the cursor at line L and column C.
- Move the cursor up N lines:
\033[<N>A
- Move the cursor down N lines:
\033[<N>B
- Move the cursor forward N columns:
\033[<N>C
- Move the cursor backward N columns:
\033[<N>D
- Save cursor position:
\033[s
- Restore cursor position:
\033[u
Cursor position save/restore seem ideal for you case, but unfortunately these two codes are not honored by many terminal emulators.
They work in xterm
and xfce4-terminal
though (except when in the last line of terminal / scrolling output, as noted by @ThomasDickey in comments). Try:
echo -e "\033[s" {1..100} "\033[u" "Overwrite"
For other terminal emulators, you can try your luck with \033[<N>A
to move cursor up for the required number of lines, and then move to column 0
.
If you know the length of your line, you can calculate how many rows does it span when (and if wrapped) with (bash
example, note the usage of COLUMNS
environment variable):
line='...'
len=${#line}
rows=$((len / COLUMNS))
and then move up with:
printf "\033[%dA" "$rows"
In Python, you could use it like:
print("\033[s", "123"*100, "\033[u", "Overwrite", sep='')
print("\033[%dA" % 3, "Overwrite", sep='')
Or, abstract all this with something like curses
.
Python solution
Based on the Move the cursor up N lines ANSI escape sequence (that should work in most terminal emulators), and a cross-Python compatible code for terminal width detection (in Python3 you can use shutil.get_terminal_size
), here's a proof-of-concept demo that works with scrolling output, adapts to line length and changing terminal width:
#!/usr/bin/env python
from __future__ import print_function
import os
import time
cnt = 0
while True:
with os.popen('stty size', 'r') as stty:
rows, columns = stty.read().split()
line = "Run: {}, Columns: {}, Filler: {}".format(cnt, columns, "***"*100)
print(line)
print("\033[{}A".format(len(line) // int(columns) + 1), end='')
time.sleep(1)
cnt += 1