How to add a progress bar to a shell script? How to add a progress bar to a shell script? shell shell

How to add a progress bar to a shell script?


You can implement this by overwriting a line. Use \r to go back to the beginning of the line without writing \n to the terminal.

Write \n when you're done to advance the line.

Use echo -ne to:

  1. not print \n and
  2. to recognize escape sequences like \r.

Here's a demo:

echo -ne '#####                     (33%)\r'sleep 1echo -ne '#############             (66%)\r'sleep 1echo -ne '#######################   (100%)\r'echo -ne '\n'

In a comment below, puk mentions this "fails" if you start with a long line and then want to write a short line: In this case, you'll need to overwrite the length of the long line (e.g., with spaces).


You may also be interested in how to do a spinner:

Can I do a spinner in Bash?

Sure!

i=1sp="/-\|"echo -n ' 'while truedo    printf "\b${sp:i++%${#sp}:1}"done

Each time the loop iterates, it displays the next character in the sp string, wrapping around as it reaches the end. (i is the position of the current character to display and ${#sp} is the length of the sp string).

The \b string is replaced by a 'backspace' character. Alternatively, you could play with \r to go back to the beginning of the line.

If you want it to slow down, put a sleep command inside the loop (after the printf).

A POSIX equivalent would be:

sp='/-\|'printf ' 'while true; do    printf '\b%.1s' "$sp"    sp=${sp#?}${sp%???}done

If you already have a loop which does a lot of work, you can call the following function at the beginning of each iteration to update the spinner:

sp="/-\|"sc=0spin() {   printf "\b${sp:sc++:1}"   ((sc==${#sp})) && sc=0}endspin() {   printf "\r%s\n" "$@"}until work_done; do   spin   some_work ...doneendspin


Got an easy progress bar function that i wrote the other day:

#!/bin/bash# 1. Create ProgressBar function# 1.1 Input is currentState($1) and totalState($2)function ProgressBar {# Process data    let _progress=(${1}*100/${2}*100)/100    let _done=(${_progress}*4)/10    let _left=40-$_done# Build progressbar string lengths    _fill=$(printf "%${_done}s")    _empty=$(printf "%${_left}s")# 1.2 Build progressbar strings and print the ProgressBar line# 1.2.1 Output example:                           # 1.2.1.1 Progress : [########################################] 100%printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%%"}# Variables_start=1# This accounts as the "totalState" variable for the ProgressBar function_end=100# Proof of conceptfor number in $(seq ${_start} ${_end})do    sleep 0.1    ProgressBar ${number} ${_end}doneprintf '\nFinished!\n'

Or snag it from,
https://github.com/fearside/ProgressBar/