How to Add a Progress Bar to a Shell Script
When writing shell scripts in Bash (or other *NIX shells), adding a progress bar can improve the user experience, especially when executing long-running tasks like file transfers, backups, or compressions. This post explores several techniques to implement progress bars, with different examples from the ones you’ve seen before.
1. Simple Progress Bar Using printf
A simple and effective method is using printf
and \r
to update the terminal line. Here’s how you can create a basic progress bar that shows the completion percentage as the task progresses:
#!/bin/bash
total=50 # Total units to represent
for ((i=1; i<=total; i++)); do
sleep 0.1 # Simulate some work being done
progress=$((i * 100 / total))
printf "\rProgress: [%-50s] %d%%" $(head -c $((i)) < /dev/zero | tr '\0' '#') $progress
done
echo -e "\nTask complete!"
Explanation:
- The
head -c
andtr
combination fills the progress bar with#
symbols as the loop progresses. \r
returns the cursor to the beginning of the line, allowing you to overwrite the previous output without creating new lines.- The
sleep
simulates work being done.
2. Progress Bar for Copy Operations with rsync
If you’re performing copy or sync operations, tools like rsync
already have a built-in progress option. You can use the --progress
flag to track the status of file transfers:
rsync --progress /source/directory /destination/directory
The --progress
flag gives detailed output, including how much data has been copied, how much is left, and the estimated time for completion.
3. Advanced Progress Bar with a Function
To reuse the progress bar logic in multiple parts of your script, you can encapsulate it into a function. This function calculates the percentage and displays the progress accordingly.
#!/bin/bash
# Function to display a progress bar
progress_bar() {
local current=$1
local total=$2
local width=50
local progress=$((current * width / total))
local remaining=$((width - progress))
printf "\r[%-${width}s] %d%%" $(head -c $progress < /dev/zero | tr '\0' '#') $((current * 100 / total))
}
# Simulate a task with a progress bar
total_steps=100
for step in $(seq 1 $total_steps); do
sleep 0.1
progress_bar $step $total_steps
done
echo -e "\nCompleted!"
Explanation:
progress_bar
takes the current step and the total steps as input to calculate the percentage.- The
printf
and string manipulation fill the bar dynamically as the task progresses.
4. Spinner for Long Tasks
Instead of a progress bar, sometimes a spinner can give users visual feedback for long-running operations. Here’s a simple spinner implementation:
#!/bin/bash
spinner() {
local sp='/-\|'
local delay=0.1
while :; do
for i in {0..3}; do
printf "\r%s" "${sp:i:1}"
sleep $delay
done
done
}
# Example usage
echo "Processing..."
spinner & # Run spinner in the background
SPINNER_PID=$!
# Simulate a long task
sleep 10
# Stop the spinner
kill $SPINNER_PID
echo -e "\nDone!"
Explanation:
- The spinner rotates characters (
/
,-
,\
,|
) to simulate progress. spinner &
runs the spinner in the background, allowing the main task to continue.- After the task completes,
kill
stops the spinner.
5. Using pv
for Piped Progress Tracking
pv
is a tool that visualizes the progress of data being piped through it. It’s particularly useful for tracking the progress of file transfers or compression operations.
Example usage for copying a file:
pv source_file > destination_file
For a more practical example, let’s say you’re compressing a large directory:
tar cf - /path/to/directory | pv | gzip > archive.tar.gz
Here, pv
shows the progress of the compression, including the speed and estimated time remaining.
6. Progress Bar with Percentage in a Loop
You can combine both a progress bar and a percentage indicator in a loop. This method gives users both visual and numerical feedback.
#!/bin/bash
# Variables
total=20
current=0
# Display progress
while [ $current -le $total ]; do
# Calculate progress percentage
percent=$((current * 100 / total))
# Draw progress bar
bar=$(printf "%-${total}s" "#" | head -c $current)
# Print progress bar and percentage
printf "\r[%-20s] %d%%" "$bar" "$percent"
# Simulate work
sleep 0.5
current=$((current + 1))
done
echo -e "\nProcess complete!"
Explanation:
printf
prints the progress bar (#
) and updates the percentage.- The
sleep
simulates task progression over time.
Adding a progress bar or spinner to your shell scripts enhances user interaction, especially when tasks take a long time. Whether using printf
for custom progress bars, the built-in --progress
in rsync
, or external tools like pv
, these approaches can be tailored to your specific needs. Now you can provide real-time feedback to users while your shell scripts perform lengthy operations.
0 Comments:
Post a Comment
Note: only a member of this blog may post a comment.
<< Home