Bash 使命令的输出显示在单行上
是否可以获取命令的输出—例如,Bash 使命令的输出显示在单行上,bash,command,overwrite,Bash,Command,Overwrite,是否可以获取命令的输出—例如,tar—将每行输出只写入一行 用法示例: tar -options -f dest source | [insert trickery here] 输出将显示正在处理的每个文件,而不移动屏幕:每个输出将覆盖最后一个文件。能做到吗 编辑:我们似乎有一个可行的答案,但让我们更进一步: 做同样的事情,但是超过5行怎么样?您会看到一个不影响终端其余部分的滚动输出。我想我已经得到了答案,但我想看看你们的想法。用回车替换换行符 tar -options -f dest s
tar
—将每行输出只写入一行
用法示例:
tar -options -f dest source | [insert trickery here]
输出将显示正在处理的每个文件,而不移动屏幕:每个输出将覆盖最后一个文件。能做到吗
编辑:我们似乎有一个可行的答案,但让我们更进一步:
做同样的事情,但是超过5行怎么样?您会看到一个不影响终端其余部分的滚动输出。我想我已经得到了答案,但我想看看你们的想法。用回车替换换行符
tar -options -f dest source | cut -b1-$(tput cols) | sed -u 'i\\o033[2K' | stdbuf -o0 tr '\n' '\r'; echo
说明:
:如果tar的输出长于终端的宽度,则截断该输出。这取决于您希望终端移动的程度,并不是严格必要的cut-b1-$(tput cols)
:在每一行的开头插入一行空格。sed的sed-u'i\\o033[2K'
选项将其置于无缓冲模式。-u
也同样有效stdbuf-oL sed'i\\033[2K'
:使用stdbuf-o0tr'\n'\r'
交换换行符和回车符。stdbuf确保输出是无缓冲的;如果没有tr
,在行缓冲的终端上,我们将看不到输出\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代码外,它完全不依赖任何东西。多亏了Dave/tripleee的核心机制(用回车替换换行符),这里有一个实际工作的版本:
tar [opts] [args] | perl -e '$| = 1; while (<>) { s/\n/\r/; print; } print "\n"'
(您还可以通过更多的perl-y方式获得终端宽度;不过我不想依赖CPAN模块
tar -options -f dest source | cut -b1-$(tput cols) | perl -ne 's/^/\e[2K/; s/\n/\r/; print' ;echo
说明:
这是为了确保列不会太宽|剪切-b1-$(tput cols)
- (在perl-ne中)
此代码清除当前行,擦除“旧”行。这应该在行的开头,以确保保留输出的最后一行,并确保在下一行可用之前不删除任何行s/^/\e[2K/
- (在perl-ne中)
当然可以在这里使用s/\n/\r/
命令tr
PS澄清:有两个明显的“线宽”问题。这两个问题都必须解决。(1)我们需要清除线条,这样短线条就不会与旧的、长的线条混淆。(2)如果一行很长,并且比当前的终端宽度宽,那么我们需要修剪它。或者使用回车符,导致下一行覆盖:
tr'\012'\015'
我认为您希望在结尾处打印一个换行,这样当它完成时就不会弄乱您的提示。我不认为这是OP想要的一点也不。他想要一些控制字符的把戏(带退格什么的),所以输出都写在同一个位置。我不知道为什么每个人都这么做;它不起作用,因为标准输出不会被刷新。@Dave,sed
,使用得很好,但我认为应该是|cut-b1-$(tput cols)| sed-u'I\\o033[2K'|tr'\n'\r';echo
,使用cut来修剪覆盖线。它也不喜欢这种方法。不管出于什么原因,管道都被忽略了。另外,Perl是否对每个人都有效,还是必须先安装它?它也不适用于cp
。cp
没有抱怨,但它也不做它应该做的事情。n以太做前面的回答=[@CJxD:我测试了这个。它在Ubuntu上对我绝对有效。你可能在另一个平台上,tar
将其输出发送到stderr而不是stdout?在这种情况下,你需要在管道之前添加2>&1
,将stderr重定向到stdout,这样管道就会捕获它。@CJxD:哦,我看到你对另一个关于tar将所有内容都作为参数。您确定tar命令中没有引用问题吗?Bash解释命令行,对管道执行自己的操作,并将参数赋给tar
;tar
无法获取管道,除非您将其转义,否则Bash不会赋予它特殊意义。我使用它进行了测试s命令:tar xvf foo.tar.gz | perl…
@jefromi:我想这听起来比平台向stderr发送正常输出更可能……如果它在行尾,就不会有输出;它打印的每一行都会立即输出erase@Dave,我已经更新了一点工作。这样可以吗:这是在开始,以便“。确保在下一行可用之前不删除任何行。”@AaronMcDaid没关系
tar -options -f dest source | cut -b1-$(tput cols) | perl -ne 's/^/\e[2K/; s/\n/\r/; print' ;echo