是否可以获取命令的输出 - 例如tar
- 将每行输出写入一行?
使用示例:
tar -options -f dest source | [insert trickery here]
并且输出将显示正在处理的每个文件而不使屏幕移动:每个输出都会覆盖最后一个。可以吗?
编辑:我们似乎有一个可行的答案,但让我们进一步: 怎么样做,但超过5行?您会看到一个滚动输出,不会影响终端的其余部分。我想我已经得到了答案,但我想看看你们的想法。
答案 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)
这是为了确保列不会太宽。s/^/\e[2K/
此代码清除当前行,删除“旧”行。这应该在行的开头,以确保保留最后一行输出,并确保在下一行可用之前我们不删除行。s/\n/\r/
当然可以在这里使用tr
命令。但是一旦我开始使用perl,我坚持使用它PS 澄清:有两个截然不同的“行宽”问题。两者都必须解决。 (1)我们需要清除线条,以便短线不与较旧的较长线条混合。 (2)如果一条线很长,并且比当前终端宽度宽,那么我们需要修剪它。