Make output of command appear on single line [closed]

做~自己de王妃 提交于 2020-06-25 01:18:32

问题


Is it possible to get the output of a command - for example tar - to write each line of output to one line only?

Example usage:

tar -options -f dest source | [insert trickery here]

and the output would show every file being processed without making the screen move: each output overwrites the last one. Can it be done?


Edit: we seem to have a working answer, but lets take it further: How about doing the same, but over 5 lines? You see a scrolling output that doesn't affect the rest of the terminal. I think I've got an answer, but I'd like to see what you guys think.


回答1:


Replace the newlines with carriage returns.

 tar -options -f dest source | cut -b1-$(tput cols) | sed -u 'i\\o033[2K' | stdbuf -o0 tr '\n' '\r'; echo

Explanation:

  • cut -b1-$(tput cols): Truncates the output of tar if it is longer than the terminal is wide. Depending on how little you want your terminal to move, it isn't strictly necessary.

  • sed -u 'i\\o033[2K': Inserts a line blank at the beginning of each line. The -u option to sed puts it in unbuffered mode. stdbuf -oL sed 'i\\033[2K' would work equally as well.

  • stdbuf -o0 tr '\n' '\r': Uses tr to exchange newlines with carriage returns. Stdbuf makes sure that the output is unbuffered; without the \n's, on a line buffered terminal, we'd see no output.

  • echo: Outputs a final newline, so that the terminal prompt doesn't eat up the final line.

For the problem your edit proposes:

x=0; 
echo -e '\e[s'; 
tar -options -f dest source | while read line; do
      echo -en "\e[u" 
      if [ $x gt 0 ]; then echo -en "\e["$x"B"; fi;
      echo -en "\e[2K"
      echo -n $line | cut -b1-$(tput cols);
      let "x = ($x+1)%5";
done; echo;

Feel free to smush all that onto one line. This actually yields an alternative solution for the original problem:

echo -e '\e[s'; tar -options -f dest source | while read line; do echo -en "\e[u\e2K"; echo -n $line | cut -b1-$(tput cols); done; echo

which neatly relies on nothing except VT100 codes.




回答2:


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.




回答3:


tar -options -f dest source | cut -b1-$(tput cols) | perl -ne 's/^/\e[2K/; s/\n/\r/; print' ;echo

Explanations:

  • | cut -b1-$(tput cols) This is in order to make sure that the columns aren't too wide.
  • (In perl -ne) s/^/\e[2K/ This code clears the current line, erasing 'old' lines. This should be at the start of the line, in order to ensure that the final line of output is preserved and also to ensure that we don't delete a line until the next line is available.
  • (In perl -ne) s/\n/\r/ The tr command could be used here of course. But once I started using perl, I stuck with it

PS To clarify: There are two distinct 'line-width' problems. Both must be solved. (1) We need to clear the lines, so that a short line isn't mixed up with older, longer lines. (2) If a line is very long, and is wider than the current terminal width, then we need to trim it.



来源:https://stackoverflow.com/questions/8748076/make-output-of-command-appear-on-single-line

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!