The Cookie Machine - Click here to drag window

DUMMY TEXT - Real text set in assets/js/theCookieMachine.js

Views: 464,853β€…    Votes:  4β€…
Tags: bash   shell   progress-bar   zsh  
Link: πŸ” See Original Answer on Stack Overflow πŸ”—

Title: How to add a progress bar to a shell script?
ID: /2021/01/01/How-to-add-a-progress-bar-to-a-shell-script_
Created: January 1, 2021
Upload: November 24, 2022    Layout:  post
TOC: false    Navigation:  false    Copy to clipboard:  false

I needed a progress bar that would fit in popup bubble message (notify-send) to represent TV volume level. Recently I’ve been writing a music player in python and the TV picture is turned off most of the time.

Sample output from terminal


Bash script


# Show a progress bar at step number $1 (from 0 to 100)

function is_int() { test "$@" -eq "$@" 2> /dev/null; } 

# Parameter 1 must be integer
if ! is_int "$1" ; then
   echo "Not an integer: ${1}"
   exit 1

# Parameter 1 must be >= 0 and <= 100
if [ "$1" -ge 0 ] && [ "$1" -le 100 ]  2>/dev/null
    echo bad volume: ${1}
    exit 1

# Main function designed for quickly copying to another program 
Main () {

    Bar=""                      # Progress Bar / Volume level
    Len=25                      # Length of Progress Bar / Volume level
    Div=4                       # Divisor into Volume for # of blocks
    Fill="β–’"                    # Fill up to $Len
    Arr=( "β–‰" "β–Ž" "β–Œ" "β–Š" )     # UTF-8 left blocks: 7/8, 1/4, 1/2, 3/4

    FullBlock=$((${1} / Div))   # Number of full blocks
    PartBlock=$((${1} % Div))   # Size of partial block (array index)

    while [[ $FullBlock -gt 0 ]]; do
        Bar="$Bar${Arr[0]}"     # Add 1 full block into Progress Bar
        (( FullBlock-- ))       # Decrement full blocks counter

    # If remainder zero no partial block, else append character from array
    if [[ $PartBlock -gt 0 ]]; then

    while [[ "${#Bar}" -lt "$Len" ]]; do
        Bar="$Bar$Fill"         # Pad Progress Bar with fill character

    echo Volume: "$1 $Bar"
    exit 0                      # Remove this line when copying into program
} # Main

Main "$@"

Test bash script

Use this script to test the progress bar in the terminal.


# test_progress_bar3

Main () {

    tput civis                              # Turn off cursor
    for ((i=0; i<=100; i++)); do
        CurrLevel=$(./progress_bar3 "$i")   # Generate progress bar 0 to 100
        echo -ne "$CurrLevel"\\r            # Reprint overtop same line
        sleep .04
    echo -e \\n                             # Advance line to keep last progress
    echo "$0 Done"
    tput cnorm                              # Turn cursor back on
} # Main

Main "$@"


This section details how notify-send is used to quickly spam popup bubble messages to the desktop. This is required because volume level can change many times a second and the default bubble message behavior is for a message to stay on the desktop for many seconds.

Sample popup bubble message


From the script above the main function was copied to a new functioned called VolumeBar in an existing bash script called tvpowered. The exit 0 command in the copied main function was removed.

Here’s how to call it and let Ubuntu’s notify-send command know we will be spamming popup bubble message:

VolumeBar $CurrVolume
# Ask Ubuntu:
notify-send --urgency=critical "tvpowered" \
    -h string:x-canonical-private-synchronous:volume \
    --icon=/usr/share/icons/gnome/48x48/devices/audio-speakers.png \
    "Volume: $CurrVolume $Bar"

This is the new line which tells notify-send to immediately replace last popup bubble:

-h string:x-canonical-private-synchronous:volume \

volume groups the popup bubble messages together and new messages in this group immediately replaces the previous. You can use anything instead of volume.

⇧ Does the Ubuntu Newsletter still get sent over email? How to stop "cable snake" symbol from appearing in taskbar?  β‡©