Create a progress bar in bash
How can I create an progress bar with bash?
This is my script:
#!/bin/bash
pass='number1 number12 number13 number14 number15 number16'
chk='number14'
for i in $pass ; do
if [ "$i" == "$chk" ]; then
echo ' Found ^_^'
else
echo 'loading 50%'
fi
done
I want to replace echo 'loading 50%'
with anything to create an progress bar.
Solution 1:
whiptail
comes preinstalled on Ubuntu and many other distros, and will show full-screen (but still terminal-based) progress elements.
dialog
is a superset of whiptail
, so this example will work equally well with both. It does provide more advanced UI elements, so it may come in handy if you're looking for user interaction such as file pickers and forms, but it has the disadvantage of not coming preinstalled on many systems.
for i in $(seq 1 100)
do
sleep 0.1
echo $i
done | whiptail --title 'Test script' --gauge 'Running...' 6 60 0
Note that the script output is interpreted as a percentage, so you may have to adjust your output accordingly.
Whiptail and Dialog also allow you to modify the text at run time via a rather cryptic syntax:
phases=(
'Locating Jebediah Kerman...'
'Motivating Kerbals...'
'Treating Kessler Syndrome...'
'Recruiting Kerbals...'
)
for i in $(seq 1 100); do
sleep 0.1
if [ $i -eq 100 ]; then
echo -e "XXX\n100\nDone!\nXXX"
elif [ $(($i % 25)) -eq 0 ]; then
let "phase = $i / 25"
echo -e "XXX\n$i\n${phases[phase]}\nXXX"
else
echo $i
fi
done | whiptail --title 'Kerbal Space Program' --gauge "${phases[0]}" 6 60 0
pv
shows the progress of a file or stream being piped through it. It cannot however be (easily?) used to show progress of a custom operation such as a loop. It's designed specifically for streams.
$ head -c 1G < /dev/urandom | pv -s 1G > /dev/null
277MB 0:00:16 [17.4MB/s] [========> ] 27% ETA 0:00:43
Some real-world examples where pv
comes in handy:
# progress while importing a DB dump
pv mybigfile.sql | mysql -uroot -p dbname
# importing straight from a remote server
ssh user@server 'cat mybigfile.sql.gz' | pv | gzip -cd | mysql -uroot -p dbname
# taking a snapshot of a btrfs partition
btrfs send /snapshots/$date | pv | btrfs receive /mnt/backup/root
I don't know of any commands that give one-line progress bars in the style of pv
or wget
, but there are plenty of simple Bash/Perl/sed scripts that will add that functionality, as others have shared here.
Solution 2:
You can use zenity
to create simple GTK dialog windows. One of the available options is a progress bar dialog.
You create such a window using zenity --progress
. To make it useful, you should specify more information by adding some of the options below (excerpt from man zenity
):
Progress options
--text=STRING
Set the dialog text
--percentage=INT
Set initial percentage
--auto-close
Close dialog when 100% has been reached
--auto-kill
Kill parent process if cancel button is pressed
--pulsate
Pulsate progress bar
--no-cancel
Hides the cancel button
There are two modes:
pulsating: The progress bar is pulsating, it just indicates that something is running, but does not tell anything about the progress. You do this by setting the
--pulsating
option.-
manual: You have to pipe the current progress percentage to the
zenity
command's standard input to update the progress bar.
An example for this could look like that below. Note that the previous commands are grouped to a subshell so that all the output is redirected to thezenity
dialog and not just that of the last command:(echo 10; sleep 2; echo 20; sleep 2; echo 50; sleep 2) | zenity --progress