When scripting in bash or any other shell in *NIX, while running a command that will take more than a few seconds, a progress bar is needed.
For example, copying a big file, opening a big tar file.
What ways do you recommend to add progress bars to shell scripts?
I did a pure shell version for an embedded system taking advantage of:
/usr/bin/dd's SIGUSR1 signal handling feature.
Basically, if you send a 'kill SIGUSR1 $(pid_of_running_dd_process)', it'll output a summary of throughput speed and amount transferred.
backgrounding dd and then querying it regularly for updates, and generating hash ticks like old-school ftp clients used to.
Using /dev/stdout as the destination for non-stdout friendly programs like scp
The end result allows you to take any file transfer operation and get progress update that looks like old-school FTP 'hash' output where you'd just get a hash mark for every X bytes.
This is hardly production quality code, but you get the idea. I think it's cute.
For what it's worth, the actual byte-count might not be reflected correctly in the number of hashes - you may have one more or less depending on rounding issues. Don't use this as part of a test script, it's just eye-candy. And, yes, I'm aware this is terribly inefficient - it's a shell script and I make no apologies for it.
Examples with wget, scp and tftp provided at the end. It should work with anything that has emits data. Make sure to use /dev/stdout for programs that aren't stdout friendly.
Examples:
This is only applicable using gnome zenity. Zenity provides a great native interface to bash scripts: https://help.gnome.org/users/zenity/stable/
From Zenity Progress Bar Example:
A simpler method that works on my system using the pipeview ( pv ) utility.
I would also like to contribute my own progress bar
It achieves sub-character precision by using Half unicode blocks
Code is included
Some posts have showed how to display the command's progress. In order to calculate it, you'll need to see how much you've progressed. On BSD systems some commands, such as dd(1), accept a
SIGINFO
signal, and will report their progress. On Linux systems some commands will respond similarly toSIGUSR1
. If this facility is available, you can pipe your input throughdd
to monitor the number of bytes processed.Alternatively, you can use
lsof
to obtain the offset of the file's read pointer, and thereby calculate the progress. I've written a command, named pmonitor, that displays the progress of processing a specified process or file. With it you can do things, such as the following.An earlier version of Linux and FreeBSD shell scripts appears on my blog.
use the linux command pv:
http://linux.die.net/man/1/pv
it doesn't know the size if it's in the middle of the stream, but it gives a speed and total and from there you can figure out how long it should take and get feedback so you know it hasn't hung.