A popular method for getting progress bars on the command line is to use the carriage return character, which overwrites the previous line, as seen in this script:
#!/bin/bash
echo -ne '[# ] 25%\r'
sleep 1
echo -ne '[## ] 50%\r'
sleep 1
echo -ne '[### ] 75%\r'
sleep 1
echo -ne '[####] 100%\r'
This is OK... if you only want print a progress bar. But a more sophisticated script may want to print a progress bar WHILE also outputting diagnostic output. You'd like the buffer of your command line application to evolve as follows (separated with ----
):
[# ] 25%
----
msg1
[# ] 25%
----
msg1
msg2
[# ] 25%
----
msg1
msg2
[## ] 50%
etc. And now, the popular approach fails:
#!/bin/bash
echo -ne '[# ] 25%\r'
echo "msg 1"
sleep 1
echo "msg 2"
echo -ne '[## ] 50%\r'
echo "msg 3"
sleep 1
echo "msg 4"
echo -ne '[### ] 75%\r'
sleep 1
echo -ne '[####] 100%\r'
outputs
ezyang@sabre:~$ ./test.sh
msg 1] 25%
msg 2
msg 3] 50%
msg 4
It would seem that to implement this, any other time you want to print a message, you need to:
- Check if it's a progress bar,
- If it is, clear the line, print your output plus a newline, and then reprint the progress bar
(Alternately, you could use ncurses). Unfortunately, this requires every possible thing which could give output to play ball.
Is there any modular method for making this kind of progress bar work, which doesn't require instrumenting all other methods of outputting to the terminal?