命令输出显示在单行上

时间:2012-01-05 18:52:52

标签: bash command overwrite

是否可以获取命令的输出 - 例如tar - 将每行输出写入一行?

使用示例:

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

并且输出将显示正在处理的每个文件而不使屏幕移动:每个输出都会覆盖最后一个。可以吗?


编辑:我们似乎有一个可行的答案,但让我们进一步: 怎么样做,但超过5行?您会看到一个滚动输出,不会影响终端的其余部分。我想我已经得到了答案,但我想看看你们的想法。

3 个答案:

答案 0 :(得分:6)

用回车替换换行符。

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

说明:

  • cut -b1-$(tput cols):如果tar的输出长于终端宽,则截断tar的输出。根据您希望终端移动的程度,这不是必需的。

  • sed -u 'i\\o033[2K':在每行的开头插入一行空白。 sed的-u选项将其置于无缓冲模式。 stdbuf -oL sed 'i\\033[2K'同样也可以。

  • stdbuf -o0 tr '\n' '\r':使用tr与回车交换换行符。 Stdbuf确保输出无缓冲;没有\n的,在线路缓冲终端上,我们看不到输出。

  • echo:输出最终换行符,以便终端提示符不会占用最后一行。

针对您的编辑建议的问题:

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;

随意将所有内容刷到一行上。这实际上为原始问题提供了另一种解决方案:

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

除了VT100代码之外什么都不依赖。

答案 1 :(得分:4)

感谢Dave / tripleee的核心机制(用回车代替换行),这里有一个实际可行的版本:

tar [opts] [args] | perl -e '$| = 1; while (<>) { s/\n/\r/; print; } print "\n"'

设置$|会导致perl在每个print之后自动刷新,而不是等待换行,并且尾随换行符会在命令完成和bash时保持最后一行输出被(部分)覆盖打印提示。 (如果它是偏的,那真是太丑了,提示和光标后面是输出行的其余部分。)

使用tr完成此操作会很高兴,但我不知道如何强制tr(或任何类似的标准)来刷新标准输出。

编辑:以前的版本实际上是丑陋的,因为在输出之后它不会清除行的其余部分。这意味着较长行后面的较短行具有剩余的尾随文本。这(当然是丑陋的)修复了:

tar [opts] [args] | perl -e '$| = 1; $f = "%-" . `tput cols` . "s\r"; $f =~ s/\n//; while (<>) {s/\n//; printf $f, $_;} print "\n"'

(你也可以用更多的方式获得终端宽度,as described here;我不想依赖CPAN模块。

答案 2 :(得分:4)

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

说明:

  • | cut -b1-$(tput cols)这是为了确保列不会太宽。
  • (在perl -ne中)s/^/\e[2K/此代码清除当前行,删除“旧”行。这应该在行的开头,以确保保留最后一行输出,并确保在下一行可用之前我们不删除行。
  • (在perl -ne中)s/\n/\r/当然可以在这里使用tr命令。但是一旦我开始使用perl,我坚持使用它

PS 澄清:有两个截然不同的“行宽”问题。两者都必须解决。 (1)我们需要清除线条,以便短线不与较旧的较长线条混合。 (2)如果一条线很长,并且比当前终端宽度宽,那么我们需要修剪它。