9

In a bash script sometimes you need the user to wait some seconds for a background process to finish.

I usually use for example:

sleep 10

How can I add a kind of progressbar to the script, so the user knows how long to wait?

I installed the command bar but I don't understand the manual.

2
  • Bash FAQ 44
    – jasonwryan
    Sep 30, 2013 at 5:18
  • I saw that, but it is only usable for copying files. In that case, I added another answer below
    – rubo77
    Sep 30, 2013 at 5:28

5 Answers 5

16
while true;do echo -n .;sleep 1;done &
sleep 10 # or do something else here
kill $!; trap 'kill $!' SIGTERM
echo done

this will start an infinite while loop that echos a spinner every second, executed in the background.

Instead of the sleep 10 command run any command you want.

When that command finishes executing this will kill the last job running in the background (which is the infinite while loop)

source: https://stackoverflow.com/a/16348366/1069083

You can use various while loops instead, e.g. a spinner like this:

while :;do for s in / - \\ \|; do printf "\r$s";sleep 1;done;done
7

This should be enough to get you started:

#!/bin/bash

for i in {001..100}; do
    sleep 1
    printf "\r $i"

done

Using the \r escape sequence returns the line to the start without a newline. This allows you to update the output without having hundreds of lines of output. By using this base, you could find a way to slowly print out an arrow such as =>25% ==>50% ===>75% instead of simply printing a number out. You could do this in a very basic way by using if-then logic to print out a specific number of ='s depending on the size of the number.

2

Here's one using cursor movements that will rewrite the line in order to show a countdown:

c=5 # seconds to wait
REWRITE="\e[25D\e[1A\e[K"
echo "Starting..."
while [ $c -gt 0 ]; do 
    c=$((c-1))
    sleep 1
    echo -e "${REWRITE}$c"
done
echo -e "${REWRITE}Done."
2

If you're looking for a way to add a progress bar to a timer with fixed sleeping time, you can also use a combination of echos and pv:

while true; do echo -n .; sleep 1; done | pv -s 10 -S -F '%t %p' > /dev/null

This produces a timer with progress bar:

0:00:02 [=====================>                                                      ] 30%

Explanation

  • while true; do echo -n .; sleep 1; done infinitely prints a . once a second.
  • | pv -s 10 -S -F '%t %p' pipes the output to pv that generates the progress bar
    • -s SIZE, --size SIZE defines the number of characters to expect
    • -S, --stop-at-size tells pv to stop after SIZE characters
    • -F FORMAT, --format FORMAT select what to print: elapsed time %t and progress bar %p
  • > /dev/null prevents printing the outputs of our echo to the terminal (they are piped through by pv)
  • select the timer duration with the -s flag (-s 10 → 10 characters → 10 seconds)
1

In case you want to see the progress of a file-copy process, you can simply use

pv source_file > destination_file

or

rsync --progress source_file destination_file

instead of the cp command

You must log in to answer this question.

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