9

In bash you can cast a command named clear to clear all the screen commands.

And with echo you can print whatever you want onscreen..

In my simple scripts I often have the need of print a percentage of what's being done with my commands..

So I could do something like..

echo "89%"
echo "90%"
echo "91%"

and so on..

what I hate is getting the screen full of percent updates...

89%
90%
91%
...

what I would like is to learn if there's a special character combination (eg. "\033[01;31m") that could be echoed with bash or php echo and tells the console "remove the last previous printed character.."

doing so by using something like: (php example)

echo str_repeat($neg_character, strlen($last_percentage_update_string));
echo $new_percentage_update_string;

I would get the new string printed at the exact position of the previous one without have the screen full of lines

Otherwise I look for an approach to do the same in other ways always using bash and php scripts (please include actual working examples at least with a debian9 console and php7)

1 Answer 1

24

The typical way of doing this is not to erase a single character, but to go back to the start of the line using a carriage return (\r):

printf "89%%"; sleep 1; printf "\r90%%\n"

Note that this doesn’t clear the line, so you need to take care of that if necessary. Simple options are adding spaces to the end, or making the output fixed-width (e.g. printf "%2d%%\n" 1 gives a leading space).

There are terminal escapes which will allow you to move around and clear parts of the screen, the CSI sequences, but they are terminal-dependent (although in practice VT100 escapes are supported everywhere now). For example

printf "89%%"; sleep 1; printf "\e[3D90%%\n"

uses ␛[3D to move three characters to the left, and writes over them (assuming your printf supports \e);

printf "89%% hello"; sleep 1; printf "\e[0E\e[K90%%\n"

uses ␛[0E to move to the beginning of the current line, and ␛[K to clear to the end of the line (assuming your terminal supports those sequences).

tput provides a terminal- and printf-agnostic way of accessing these sequences:

printf "89%%"; sleep 1; tput cub 3; tput el; printf "90%%\n"

will move the cursor to the left three times (cub 3) and clear to the end of the line (el), using whatever character sequence is appropriate for the current terminal;

printf "89%% hello"; sleep 1; tput hpa 0; tput el; printf "90%%\n"

will move the cursor to the left-most column (hpa 0) and clear to the end of the line.

man terminfo will tell you what “capability name” to use with tput.

(Note that a lot of the specifics of the examples above assume that all your output is on the same line. They’re not supposed to be fool-proof, only to illustrate various approaches.)

For similar screen control in PHP scripts, you could look at the PECL ncurses extension.

13
  • 5
    One can usually use tput cub 3 to move the cursor back by 3 columns without having to hardcode the sequence (and tput el to erase the line). Aug 23, 2018 at 10:29
  • 1. \e isnt portable 2. neither is \e[0E
    – Zombo
    Aug 23, 2018 at 11:37
  • Thanks @Steven, I’d mentioned that the sequences were terminal-dependent but I’ve added some more qualifiers. Aug 23, 2018 at 11:40
  • One could use ech for erasure. And moving backwards by 3 positions has a gotcha, and two possible optimizations that full-screen programs tend to use. But both optimizations and erasure are overkill for simple current-line-only terminal stuff, when one follows that advice to use a fixed-width format specifier. Don't forget that 100 is 3 digits long, by the way. (-:
    – JdeBP
    Aug 23, 2018 at 16:53
  • Good points @JdeBP, thanks. Once you hit 100%, I sure hope you no longer need progress updates ;-). Aug 23, 2018 at 16:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .