How to show and update echo on same line

Solution 1:

Well I did not read correctly the man echo page for this.

echo had 2 options that could do this if I added a 3rd escape character.

The 2 options are -n and -e.

-n will not output the trailing newline. So that saves me from going to a new line each time I echo something.

-e will allow me to interpret backslash escape symbols.

Guess what escape symbol I want to use for this: \r. Yes, carriage return would send me back to the start and it will visually look like I am updating on the same line.

So the echo line would look like this:

echo -ne "Movie $movies - $dir ADDED!"\\r

I had to escape the escape symbol so Bash would not kill it. that is why you see 2 \ symbols in there.

As mentioned by William, printf can also do similar (and even more extensive) tasks like this.

Solution 2:

If I have understood well, you can get it replacing your echo with the following line:

echo -ne "Movie $movies - $dir ADDED! \033[0K\r"

Here is a small example that you can run to understand its behaviour:

#!/bin/bash
for pc in $(seq 1 100); do
    echo -ne "$pc%\033[0K\r"
    sleep 1
done
echo

Solution 3:

The rest of answers are pretty good, but just wanted to add some extra information in case someone comes here looking for a solution to replace/update a multiline echo.

So I would like to share an example with you all. The following script was tried on a CentOS system and uses "timedatectl" command which basically prints some detailed time information of your system.

I decided to use that command as its output contains multiple lines and works perfectly for the example below:

#!/bin/bash
while true; do
  COMMAND=$(timedatectl) #Save command result in a var.
  echo "$COMMAND" #Print command result, including new lines.

  sleep 3 #Keep above's output on screen during 3 seconds before clearing it

  #Following code clears previously printed lines
  LINES=$(echo "$COMMAND" | wc -l) #Calculate number of lines for the output previously printed
  for (( i=1; i <= $(($LINES)); i++ ));do #For each line printed as a result of "timedatectl"
    tput cuu1 #Move cursor up by one line
    tput el #Clear the line
  done

done

The above will print the result of "timedatectl" forever and will replace the previous echo with updated results.

I have to mention that this code is only an example, but maybe not the best solution for you depending on your needs. A similar command that would do almost the same (at least visually) is "watch -n 3 timedatectl".

But that's a different story. :)

Hope that helps!

Solution 4:

I use printf, is shorter as it doesn't need flags to do the work:

printf "\rMy static $myvars composed text"

Solution 5:

This is vary useful please try it and change as required.

#!/bin/bash
for load in $(seq 1 100); do
    echo -ne "$load % downloded ...\r"
    sleep 1
done
echo "100"
echo "Loaded ..."