View script Copied!
Render a single-line progress bar with percentage completion.
Designed for shell loops or long-running scripts. Instead of a one-liner printf, you get proper output stream management (defaults to stderr to keep stdout clean), automatic terminal width detection to prevent line wrapping, and smart behavior in both TTY and non-TTY contexts.
for i in {1..10}; do
progress "$i" 10
sleep 0.2
done
In a TTY, this renders an updating progress bar on stderr:
[############################# ] 50%
At completion, a newline is printed so the bar doesn't get overwritten by the next command:
[##################################################] 100%
Track processing of a file list:
files=(*.txt)
total="${#files[@]}"
current=0
for file in "${files[@]}"; do
current=$((current + 1))
progress "$current" "$total"
# process "$file"
done
Use a custom width and characters:
for i in {1..50}; do
progress --width 30 --progress-char '=' --remaining-char '.' "$i" 50
sleep 0.05
done
Renders [======================........] 100% at completion.
Force to stdout (e.g. when stderr is redirected elsewhere):
for i in {1..100}; do
progress --stdout "$i" 100
# do work
done
Redirect to a log file -- in non-TTY contexts, only the 100% bar is written:
for i in {1..100}; do
progress "$i" 100
# do work
done 2>> progress.log
The log file contains just:
[##################################################] 100%
progress is smart about where and when it writes:
\r to redraw the bar in place at each updateYou can force output to stdout with --stdout or explicitly to stderr with --stderr.
The bar width is clamped to fit the terminal so the line never wraps and breaks the \r redraw behavior. The format is:
[bar] percentage
Fixed overhead is 8 characters ([, ] , and %3d%%), so a 50-character bar setting on an 80-column terminal will be honored, but on a 40-column terminal it will be reduced to 32 characters.
Width detection uses stty, then $COLUMNS, falling back to 80.
| Flag | Description |
|---|---|
-w, --width N |
Width of the progress bar itself (default: 50), automatically clamped to fit terminal |
-p, --progress-char CHAR |
Character for the completed portion (default: #) |
-r, --remaining-char CHAR |
Character for the remaining portion (default: ) |
--stderr |
Force output to stderr |
--stdout |
Force output to stdout |
-h, --help |
Show help |
| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Usage error (missing arguments, invalid number, width <= 0) |
stty (optional, for terminal width detection)CURRENT is clamped to the range [0, MAX] -- negative values become 0, values above MAX become MAXMAX must be a positive integer (enforced)CURRENT == MAXCURRENT == MAX