Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 使命令的输出显示在单行上_Bash_Command_Overwrite - Fatal编程技术网

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
说明:

  • cut-b1-$(tput cols)
    :如果tar的输出长于终端的宽度,则截断该输出。这取决于您希望终端移动的程度,并不是严格必要的

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

  • stdbuf-o0tr'\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代码外,它完全不依赖任何东西。

多亏了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