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:
- not print
\n
and - to recognize escape sequences like
\r
.
Here's a demo:
echo -ne '##### (33%)\r'
sleep 1
echo -ne '############# (66%)\r'
sleep 1
echo -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).
How to: Progress bar in bash
Let's use echo -n '...' $'\r'
to print a carriage return:
for ((k = 0; k <= 10 ; k++))
do
echo -n "[ "
for ((i = 0 ; i <= k; i++)); do echo -n "###"; done
for ((j = i ; j <= 10 ; j++)); do echo -n " "; done
v=$((k * 10))
echo -n " ] "
echo -n "$v %" $'\r'
sleep 0.05
done
echo
It makes the cursor move to the beginning of the line to keep printing.
Output is as follows, always in the same line:
[ ################## ] 50 %
.../...
[ ################################# ] 100 %
How to add progress bar to shell scripts
So basically its will be a little hack because you have no way to check the real progress of you starting process. Its more state between off/on. But if you still want to make the progress bar this code can do the job:
#!/bin/bash
function ProgressBar {
let _progress=(${1}*100/${2}*100)/100
let _done=(${_progress}*4)/10
let _left=40-$_done
_fill=$(printf "%${_done}s")
_empty=$(printf "%${_left}s")
# Progress : [########################################] 100%
printf "\rProgress : [${_fill// /\#}${_empty// /-}] ${_progress}%%"
}
# Proof of concept
work1() {
sleep 10
nc -lp 5001
}
work2() {
sleep 15
nc -lp 6001
}
work1 &
progress=1
while ! nc -z localhost 5001 ; do
ProgressBar ${progress} 100
let progress=progress+1
sleep 0.3
done
ProgressBar 100 100
echo ""
echo "Work 1 done"
work2 &
progress=1
while ! nc -z localhost 6001 ; do
ProgressBar ${progress} 100
let progress=progress+1
sleep 0.3
done
ProgressBar 100 100
echo ""
echo "Work 2 done"
echo "All services started Successfully !!!"
Again its more Microsoft style progress bare here, we passing the job from x to 100 when nc report success. You can adjust the speed sleep 0.x
Shell : How to print progressbar
I guess counter=$counter+1
does not do what you expect. It just concatenates $counter
and "+1"
. So after n iterations you'll have some sting like "1+1+...+1"
(n+1-times). You have that in the expression you pipe to bc
and operator precedence (*
before +
) then leads to the unexpected results.
Change counter=$counter+1
to also use bc
as you've done above, thus counter=$(echo "${counter}+1" | bc)
.
Or change percent_done=$(echo "${counter}*100/${1}" | bc -l )
to percent_done=$(echo "(${counter})*100/${1}" | bc -l )
(note the parenthesis) to overrule operator precedence, if for some reason you really want such a "1+1..+1"
string.
How to add Progress bar for shell scripts having few commands?
many solutions the easiest way is using externat commands like pv
du -h /var | tail -2 | pv
a nicer way can be using functions in your script for the bar display :
echo -ne '##### (33%)\r'
sleep 1
echo -ne '############# (66%)\r'
sleep 1
echo -ne '####################### (100%)\r'
echo -ne '\n'
or even better using the rolling spin :
sp='/-\|'
printf ' '
while true; do
printf '\b%.1s' "$sp"
sp=${sp#?}${sp%???}
done
you launch the task as background & bars and/or spin as foreground
of course you make conditions or traps on signals to stop it at end of task/command.
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:
- not print
\n
and - to recognize escape sequences like
\r
.
Here's a demo:
echo -ne '##### (33%)\r'
sleep 1
echo -ne '############# (66%)\r'
sleep 1
echo -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).
Using Bash to display a progress indicator
In this example using SCP, I'm demonstrating how to grab the process id (pid) and then do something while that process is running.
This displays a simple spinnng icon.
/usr/bin/scp me@website.com:file somewhere 2>/dev/null &
pid=$! # Process Id of the previous running command
spin[0]="-"
spin[1]="\\"
spin[2]="|"
spin[3]="/"
echo -n "[copying] ${spin[0]}"
while [ kill -0 $pid ]
do
for i in "${spin[@]}"
do
echo -ne "\b$i"
sleep 0.1
done
done
William Pursell's solution
/usr/bin/scp me@website.com:file somewhere 2>/dev/null &
pid=$! # Process Id of the previous running command
spin='-\|/'
i=0
while kill -0 $pid 2>/dev/null
do
i=$(( (i+1) %4 ))
printf "\r${spin:$i:1}"
sleep .1
done
Related Topics
Sharing Devices (Webcam, Usb Drives, etc) with Docker
Sort by Third Column Leaving First and Second Column Intact in Linux
Find and Replace Text in a File Between Range of Lines Using Sed
How Do Locales Work in Linux/Posix and What Transformations Are Applied
Use Sed to Delete All Leading/Following Blank Spaces in a Text File
Linux - Watch a Directory for New Files, Then Run a Script
X86 Assembly: Before Making a System Call on Linux Should You Save All Registers
Npm Can't Install Appjs. Error: Cannot Find Module 'Graceful-Fs'
How to Return Spawned Process Exit Code in Expect Script
What Is the Use of File Descriptor 255 in Bash Process
Git Pull Permission Denied Linux
Deduplicate Git Forks on a Server
X86 Linux Assembler Get Program Parameters from _Start
How to Return Memory from Process to the Os
How to Disable Socket Creation for a Linux Process, for Sandboxing
How to Erase Printed Characters in a Console Application(Linux)