‘bar’ - ‘cat’ with ASCII progress bar
This is a small shell script intended to be used in portable Unix install scripts for showing progress bars. The overall goal is to write a minimally complex shell script (thus a program that needs no compilation) that is as robust as possible to work on as many Bourne shells and operating systems as possible, and that implements ‘cat’ with an ASCII progress bar and some other nifty features. This is pure Bourne shell code. (For sh, ash, ksh, zsh, bash, ...) The script is mainly intended to be used in portable install scripts, where you can use the body of the script. |
|
Source Code |
Portability |
※ |
Shell | OS | Confirmed Script Version(s) | ||
---|---|---|---|---|
Regularly checked by myself | ||||
/bin/sh | NetBSD 1.6.2 | >= 1.2 | ||
/bin/sh | Solaris 2.9 | >= 1.0 | ||
/bin/sh | Solaris 2.8 | >= 1.2 | ||
ae 2.1.8 | Linux (Suse) | >= 1.2 | ||
ash 0.2 | Linux (Suse) | >= 1.2 | ||
bash 1.14.5 | Linux (Suse) | >= 1.2 | ||
bash 2.05.0(1) | Linux (Suse) | >= 1.0 | ||
bash 2.05.0(1) | Solaris 2.9 | >= 1.2 | ||
bash 2.05a.0(1) | Linux (Debian) | >= 1.2 | ||
bash 2.05b.0(1) | NetBSD 1.6.2 | >= 1.2 | ||
bash 3.00.0(1) | Solaris 2.8 | >= 1.2 | ||
jsh 050621 | Linux (Suse) | >= 1.3 | ||
ksh | Solaris 2.9 | >= 1.2 | ||
ksh | Solaris 2.8 | >= 1.2 | ||
pdksh 5.2.14 | Linux (Suse) | >= 1.2 | ||
pdksh 5.2.14 | NetBSD 1.6.2 | >= 1.2 | ||
zsh 4.2.5 | Linux (Suse) | >= 1.2 | ||
zsh 4.0.4 | Linux (Debian) | >= 1.2 | ||
zsh 3.0.8 | Solaris 2.9 | >= 1.2 | ||
Verified by users | ||||
ksh | AIX 5.0 | 1.3.1 | ||
/bin/sh | FreeBSD 5.3 | 1.3.1 | ||
bash | Mac OS X 10.4.6 | 1.4 | ||
bash | Fedora Core 5 | 1.4 | ||
bash 3.1 | Fedora Core 6 | 1.4 | ||
ksh | Tru64 Unix | 1.4 | ||
bash 3.2.13(1) | Ubuntu 7.04 Feisty | 1.4 | ||
bash-3.1.17 | Gentoo 2007.0 | 1.4 | ||
bash-3.2.25(1) | Ubuntu 7.10 | 1.4 | ||
ksh | OpenBSD 4.2 | 1.4 | ||
HP-UX 11i v2 (11.23) | 1.4 | |||
ksh | FreeBSD 7.1-STABLE | 1.4 | ||
/bin/sh | SunOS OpenSolaris i386 5.11 | 1.4 | ||
Bash 4.0 | ArchLinux | 1.4 |
Please help improve this project by reporting success or failure in other shells, especially in /bin/sh on other operating systems.
Examples |
※ |
Append files | |
---|---|
Standard: |
cat file1 file2 file2 > file3 |
With Progress Bar: |
bar file1 file2 file2 > file3 |
Copy a file | |
---|---|
Standard: |
cp infile outfile |
With Progress Bar: |
bar -o outfile infile |
Copy several files to another directory (showing a common progress bar) | |
---|---|
Standard: |
cp file1 file2 file2 outdir/ |
With Progress Bar: |
bar -c 'cat > outdir/${bar_file}' file1 file2 file3 |
Unpack each file individually, but have a common progress bar | |
---|---|
Standard: |
for i in *.tar.gz; do tar xzpf $i; done |
With Progress Bar: |
bar -c 'tar xzpf -' *.tar.gz |
Make a File Listing
We don't want to mention ‘.tar.gz’ in the listing, so we use ‘-e’ to append an extension in each command. | |
---|---|
Standard: |
(for file in erwin-2.0.274 bar-1.0-src linux-2.4.21 do echo ${file}: tar tzvpf ${file}.tar.gz done) > package-list.txt |
With Progress Bar: |
bar -c 'echo ${bar_file}: ; tar tzvpf -' \ -e .tar.gz \ erwin-2.0.274 \ bar-1.0-src \ linux-2.4.21 \ > package-list.txt |
Documentation |
※ |
Options Overview
For the shell script, features are usually passed on the command line, and for the shell function (but also for the script), features are passed as exported environment variables. The following tables gives an overview of the features
Cmd. Line | Env. Var | Description | ||
---|---|---|---|---|
-o FILE | use shell redirection | Redirects output to a file. | ||
-n | BAR_CLEAR=1 | After termination, clear the line with the bar instead of leaving a full bar on the console. | ||
-p | BAR_PERC=0 | Hides the percentage display. | ||
-E | BAR_ETA=0 | Hides the estimated time of arrival (ETA) display. | ||
-t | BAR_TRACE=1 | Shows the current file (trace mode). | ||
-T WIDTH | BAR_TRACE_WIDTH=WIDTH | Sets the number of characters reserved for the current file display. If not set, the default is 10. | ||
-q | BAR_OK=0 | Hides the bar completely, and reverts to the plain behaviour of cat. | ||
-c CMD | BAR_CMD=CMD | For each file, pipe the contents into CMD. The command is evaluated in the shell, you have access to the internal variables of the script. Currently, the most interesting variable is bar_file which contains the name of the current file as given on the command line, i.e., without the additional ending set by BAR_EXT. | ||
-e EXT | BAR_EXT=EXT | Sets EXT as an additional file extension to be appended to each given file. | ||
-d DIR | BAR_DIR=DIR | Sets DIR to be prefixed to each given file. Typically used for prepending directories to each file, in which case the argument must end in a slash. | ||
-b SIZE | BAR_BS=SIZE | Sets the maximal block size to use for dd. By default, this is 1048567 (= 1 MB). The command line option accepts suffixes: k for kilobytes and M for megabytes. The environment variable must be specified in bytes. | ||
-s SIZE | BAR_SIZE=SIZE | Sets the expected number of bytes expected to be processed. Under no circumstances, this may be smaller than the amount of bytes read, as the script might process less bytes of data then (but this is also not good for restricting the data flow to an exact number of bytes, since the internal counting is heuristical: the script will cut the stream at some unpredictable point after the given amount of bytes). Like -b, the command line accepts k and M suffixes, but only when the result is smaller than the numbers expr can handle. Without using suffixes, i.e., in bytes, you may specify any amount, even larger ones than expr can handle. |
||
-w WIDTH | BAR_WIDTH=WIDTH | Sets the bar width to WIDTH characters. The script tries to find a default value by using the environment variable COLUMNS. If it is not set, the default is 76. | ||
-0 CHAR | BAR_C0=CHAR | Sets the character displayed for work yet to be done. | ||
-1 CHAR | BAR_C1=CHAR | Sets the character displayed for work already done. | ||
-[ CHAR | BAR_A=CHAR | Sets the first character displayed in the bar (may be empty). | ||
-] CHAR | BAR_B=CHAR | Sets the last character displayed in the bar (may be empty). | ||
-V | Prints the version number and exits. | |||
-D |
Tries to dump the bar_cat() shell function, i.e. everything but the command line interface. The output can be included in your own scripts. This options strips comments, empty lines, and leading white space on all lines to make the result small. Some features may be removed completely from the dumped shell code by specifying the corresponding options before -D. These are: -t (trace), -p (percentage), -E (ETA) and -L (large file support). (-L only has an effect with -D.) |
|||
-D- | Same as -D, but only dumps the function body. | |||
-- | Last option: only file names follow |
Input Files
In the comment line, after the options, the input files follow. The shell function bar_cat is invoked with that list of files.
Note: If the list of files you provide to bar_cat is empty, nothing is read. To explicitly state that stdin is to be read, use the special file name /dev/stdin.
The command line interface invoked with no file names will also read from stdin.
Bugs |
※ |
- \ cannot be used as a character in the bar, since printf will interpret it. (And on systems that lack printf, but support echo 'nonewline\c', echo is likely to also interpret \ with other escape sequences.)
Fixed |
※ |
-
The program cannot read from stdin.
[Fixed in v1.1: stdin]
-
Infinite streams (like /dev/zero) don't work.
[Fixed in v1.1: inode type]
-
Special devices don't work (the size cannot be determined).
[Fixed in v1.1: inode type]
-
When neither ‘printf’ nor ‘echo -n’ is found to work, switch
off bar display just like for missing ‘dd’ or ‘grep’ -- currently,
the normal loop is executed without showing anything. This is
actually correct, but quite stupid.
[Fixed in v1.2: no echo without newline]
-
Files whose size exceeds the computation range of expr
cannot be handled properly. On 32-bit machines, this is
expected to be the case for file >= 2GB.
[Fixed in v1.2: use pattern matching to divide]
Missing Features / Future Work |
※ |
- Infinite streams are not nice: the bar is only displayed at 0% and at 100%. Have some other form of entertainment, like the ASCII-propeller: .
- Somehow find out whether stderr is a tty and if not, disable the bar.
- Even more compatibility with ksh, zsh and normal sh on many systems.
Changes |
※ |
-
Version 1.4 (Stable; Bug Fix)
※ - Bug fix: -[ and -] are now properly recognized.
-
Version 1.3.1 (Stable; Bug Fix)
※ - Bug fix: -D was broken, so the released version is 1.3.1.
-
Version 1.3(Stable; New Features; Broken, Not Released)※ - Robustness: added Heirloom Bourne shell to test suite
- Change: The default width is now 76, since it's close to a likely 80 and not just arbitrary like 60.
- Feature: To be able to get leaner code, some features can be removed completely when dumping with -D. The set of removed features is customisable: -t, -p, -E and -L.
- Feature: display estimated time of arrival (ETA). Can be switched off with -E. This currently only works in shells that have $SECONDS (i.e., bash, zsh, many kshs, maybe others).
- Feature: -D removes leading white space to make output smaller.
- Feature: -t displays current file processed, -T sets width of that display.
- Bug Fix: Typo in error message.
- Feature: Have a switch to completely hide the bar: -q(uiet).
- Feature: A switch for manually setting the expected amount of bytes: -s
- Feature: A switch to print the version number: -V
-
Version 1.2 (Stable; Bug Fixes)
※ - Bug fix: works in ae shell now
- Bug fix: works when $COLUMNS is set, but empty
- Bug fix: works when $COLUMNS is too small to show bar
- Bug fix: eliminate use of test "${VAR-unset}" = unset in favour of test -z "${VAR}" (those are not the same, but the latter is good in this script). And get rid of ${VAR-VALUE} altogether.
- Bug fix: redirect output of 'ls ...' to /dev/null in order not to interfere with displaying the bar.
- Bug fix: -p was a unary instead of a nullary option
- Cancelled Bug fix: check whether echo interprets backslashes by default, and if so, try to disable it using -E. Cancelled, since checking whether -E works is a major source of complexity. We just have to live with echo that interprets backslashes.
- Bug fix: print additional carriage return at beginning of every line in case echo needs no options (in which case it may still print a space).
- Bug fix: revert to plain cat behaviour if echo cannot be used without newline.
- Bug fix: before using -n with echo, try whether it accepts it without signalling an error.
- Bug fix: if any file is not found or is not a regular file, we currently must switch off the bar display, since the total byte amount might be totally wrong.
- Bug fix: use pattern matching to divide large numbers (=file sizes) by powers of ten so we can use expr on them.
- Bug fix: carefully check and fix all computations to be more precise.
- Bug fix: BAR_EXT (and the new BAR_DIR) did not work and lead to switching off the bar.
- Robustness: remove duplicate test -f in loop where it is never reached and in the same way, remove superfluous check for stdin.
- Robustness: check for availability of dd and grep
- Robustness: prefer echo -n over printf '%s'
- Robustness: allow echo 'xyz\c' for suppressing newline and prefer over printf
- Robustness: get rid of some unnecessary cat invocations
- Robustness: Most programs are checked fo in advance (expr, dd, grep, etc.) and plain mode is activated if something is missing. The script tries to never fail just because displaying the progress bar is not possible.
- Compatibility tests on some systems and some shells.
- Ok, and a feature: -D and -D- dump the bar_cat() function body.
- And another feature: -dDIR sets a prefix much like -e sets a suffix.
-
Version 1.1 (Beta; New Features)
※ - Bug fix: check inode type before trying to get file size.
- Bug fix: can read from stdin.
- Bug fix: % can be used as a bar character now even if printf is found.
- Feature: \r is used literally, so echo -e is not used anymore.
- Feature: clear bar after termination (-n)
- Feature: Make the [ and the ] configurable, too.
- Feature: Accept -bXYZ option style additional to -b XYZ.
- Feature: Percentage is shown (switch off with -p)
- Feature: Tries to find default terminal width automatically.
- Feature: The maximal block size is adjustable (formerly, large files made the block size argument for dd become ridiculously large.
-
Version 1.0 (Beta; Initial)
※ - Initial release.