PercBar — Create a progress bar (Bash package)
Below you find the latest version of (1) the package's README and (2) its main source file.
For the git repository and issue tracker, see the project's page on sr.ht.
For more packages, see Software.
Usage
percbar num [den len]
where:
numis the amount (numerator)denis the total (denominator)lenis the bar lengthnum ≤ den
If no den is passed, it's assumed to be 100.
If no len is passed, bar length will be 50.
Examples
Here are a few examples.
Regular
1%
# Same as percbar 1 100 percbar 1
1% 99% █░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100%
20%
# Same as percbar 20 100 percbar 20
20% 80% ██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100%
20 out of 60
percbar 20 60
33% 67%
█████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100%
20 out of 60, bar length 70
percbar 20 60 70
33% 67%
███████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100%
7 out of 21, bar length 12
percbar 7 21 12
33% 67% ████░░░░░░░░ 100%
e ÷ π
percbar 2.718281828459045 \
3.141592653589793
87% 13%
███████████████████████████████████████████░░░░░░░ 100%
24.2 ÷ 42
percbar 24.2 42
58% 42%
█████████████████████████████░░░░░░░░░░░░░░░░░░░░░ 100%
Modified
Now what if you wanted to change features of the bar?
I did consider adding some flags for options (say, -n for no total, etc). But decided against it, because:
- Version
0.2.0has less than 70 actual lines of code — which is good.
I wanted to keep it just as short and simple. - And modifying the output with a
sedfilter is simple and cheap.
So you can modify it yourself by defining one-line functions that look like these:
foo() { percbar "$@" | sed "something" ;}
Here are some examples:
20%, no % labels
foo() { percbar "$@" | sed 1d ;} foo 20
██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100%
20%, no total
foo() { percbar "$@" | sed "2 s/ .*//" ;} foo 20
20% 80% ██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
20%, but just the bar
foo() { percbar "$@" | sed "1d; s/ .*//" ;} foo 20
██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
20%, just that label
foo() { percbar "$@" | sed "s/ *[^%]*%$//" ;} foo 20
20% ██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
20%, total shown as number
foo() { percbar "$@" | sed "2 s/100%/${2:-100}/" ;} foo 20 foo 42 210 foo 8.4 42
20% 80% ██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100 20% 80% ██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 210 20% 80% ██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 42
(Replacing instead the top % labels with actual numbers is not as straightforward:
these could be of any width, so their positions would need to be recalculated for them to end up centered.)
Different block characters
foo() { percbar "$@" | sed "y/█░/●◌/" ;} foo 24.2 42
58% 42%
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌ 100%
Different block characters, just complete %
foo() { percbar "$@" | sed "y/█░/●◌/; s/ *[^%]*%$//" ;} foo 24.2 42
58%
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌
Different block characters, just complete % and the total as number
foo() { percbar "$@" | sed "y/█░/●◌/; 2 s/100%/${2:-100}/; 1 s/ *[^%]*%$//" ;} foo 24.2 42
58%
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌◌ 42
Installation
See my page Software for the most up-to-date instructions on how to download and install my packages.
Dependencies: bc must be available in your system.
Contributing
See my page Software for information about how to contribute to my packages.
License
This project follows the REUSE Specification (FAQ), which in turn is built upon SPDX.
Therefore, license and copyright information can be found in:
- each file's comment header, or
- an adjacent file of the same name with the additional extension
.license, or - the
.reuse/dep5file
The full text of the licenses can be found in the LICENSES subdirectory.
percbar
Contents
#!/usr/bin/env bash # PercBar --- Create a progress bar # SPDX-FileCopyrightText: © flandrew <https://flandrew.srht.site/listful> # SPDX-License-Identifier: GPL-3.0-or-later #---------------------# # Author: flandrew # # Created: 2018-01-26 # # Updated: 2025-10-31 # #---------------------# # Version: 0.2.0 # #---------------------# ### Commentary # # For usage, run: percbar -h # ############################################################################# ### Code # Dependencies require() { hash "$@" || exit 127 ;} require bc ############################################################################# usage() { cut -c5- <<EOU Usage: percbar num [den len] where: - num is the amount (numerator) - den is the total (denominator) - len is the bar length - num ≤ den If no den is passed, it's assumed to be 100. If no len is passed, bar length will be 50. EOU exit "${1:-0}" ;} ############################################################################# # Numbers must be composed of only digits and a maximum of one decimal point isnumber() [[ -z "$(<<<"$1" sed 's/\.//; s/[0-9]//g')" ]] # Round the number round() { <<<"$1*$2/$3 + 0.5" bc -l | sed '/^\./ s/^/0/; s/\..*//' ;} ############################################################################# main() { local pfull bfull bnorm ctpad outper fullchar num \ pempt bempt ltpad rtpad outbar emptchar den n # Parse input [[ "$1" ]] && num="$1" || usage 9 [[ "$1" == "-h" ]] && usage 0 [[ "$2" ]] && den="$2" || den=100 [[ "$3" ]] && bnorm="$3" || bnorm=50 for n in 1 2 3; do isnumber "${!n}" || { echo "Error: ${!n} is not a number" >&2 exit "$n" ;} done # Percentage numbers & Blocks in the bar ## completed, rounded pfull=$(round 100 "$num" "$den") bfull=$(round "$bnorm" "$num" "$den") ((pfull <= 100)) || { echo "Error: need 0% ≤ result ≤ 100%" >&2 exit 4 ;} ## differences ((pempt= 100 - pfull , bempt= bnorm - bfull)) # Percentages' positions ((_= bfull < 2 ? 0 : pfull < 10 ? bfull - 2 : pfull < 100 ? bfull - 3 : bnorm - 4 , ltpad= _ / 2 , _= bempt < 2 ? -2 : pfull < 10 ? bempt - 2 : pfull < 100 ? bempt - 3 : bnorm - 4 , rtpad= _ / 2 , _= pfull < 10 ? bfull - 2 : pfull < 100 ? bfull - 3 : bnorm - 4 , ctpad= _ + rtpad - ltpad)) # Produce the output outper=$(printf '%*s' "$ltpad" | tr ' ' s printf '%s' "$pfull"% printf '%*s' "$ctpad" | tr ' ' s printf '%s\n' "$pempt"%) outbar=$(printf '%*s' "$bfull" | tr ' ' f printf '%*s\n' "$bempt" | tr ' ' e) fullchar="█" # U+2588 emptchar="░" # U+2591 sed "y/s/ /" <<< "$outper" sed "y/fe/$fullchar$emptchar/ s/$/ 100%/" <<< "$outbar" } ############################################################################# main "$@" exit 0
📆 2025-11-02