Thanks to Dave/tripleee for the core mechanic (replacing newlines with carriage returns), here's a version that actually works:
tar [opts] [args] | perl -e '$| = 1; while (<>) { s/\n/\r/; print; } print "\n"'
Setting $|
causes perl to automatically flush after every print
, instead of waiting for newlines, and the trailing newline keeps your last line of output from being (partially) overwritten when the command finishes and bash prints a prompt. (That's really ugly if it's partial, with the prompt and cursor followed by the rest of the line of output.)
It'd be nice to accomplish this with tr
, but I'm not aware of how to force tr
(or anything similarly standard) to flush stdout.
Edit: The previous version is actually ugly, since it doesn't clear the rest of the line after what's been output. That means that shorter lines following longer lines have leftover trailing text. This (admittedly ugly) fixes that:
tar [opts] [args] | perl -e '$| = 1; $f = "%-" . `tput cols` . "s\r"; $f =~ s/\n//; while (<>) {s/\n//; printf $f, $_;} print "\n"'
(You can also get the terminal width in more perl-y ways, as described here; I didn't want to depend on CPAN modules though.