Bash – Print something in console in the same place of the previous echo, with a sort of negative echo

bashconsolelinuxPHP

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)

Best Answer

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.

Related Question