如何在同一行显示和更新回声


112

我在Bash中有以下内容(在Linux中)

for dir in Movies/*
do
  (cd "$dir" && pwd|cut -d \/ -f5|tr -s '\n' ', ' >> ../../movielist &&
  exiftool * -t -s3 -ImageSize -FileType|tr -s '\t' ',' >> ../../movielist )
echo "Movie $movies - $dir ADDED!"
let movies=movies+1
done

但是我希望这样做,以便“回声”在下一行显示以下回声(不与最后一个回声输出串联,而是替换它),以便使其看起来像在更新。类似于进度条的百分比显示在同一行上。

Answers:


196

好吧,我没有正确阅读此man echo页面。

如果我添加了第三个转义字符,echo有2个选项可以做到这一点。

2个选项是-n-e

-n不会输出尾随换行符。这样可以避免我每次回声时都换行。

-e 将允许我解释反斜杠转义符号。

猜猜我要为此使用什么转义符号:\r。是的,回车会把我送回起点,并且看上去我在同一行上正在更新。

因此,回声线将如下所示:

echo -ne "Movie $movies - $dir ADDED!"\\r

我必须逃脱转义符号,以便Bash不会杀死它。这就是为什么您\在那里看到2个符号的原因。

正如William所提到的,printf它也可以执行类似(甚至更广泛)的任务。


12
只是对未来的说明:printf将做完全相同的事情,没有任何选择。优点是,printf通常在每个环境和OS中的行为都相似,而echo有时的行为可能会非常不同。对于跨平台脚本(或者如果您认为自己可能对此有所关心),使用printf是最佳实践。
William T Froggard

8
printf a; printf b输出ab--- printf a\\r; printf b输出b--- printf a\\r; sleep 1; printf b输出a,然后b
XavierStuvw

64

如果我了解得很好,您可以将其替换为以下行:

echo -ne "Movie $movies - $dir ADDED! \033[0K\r"

这是一个小的示例,您可以运行以了解其行为:

#!/bin/bash
for pc in $(seq 1 100); do
    echo -ne "$pc%\033[0K\r"
    sleep 1
done
echo

似乎在zsh上这K不是必需的,实际上被当作字母K
放出。– mknaf

1
很好的例子-我在开始的哈希爆炸是关键
菲利克斯前夕

22

其余的答案都很好,但是只是想添加一些额外的信息,以防有人来这里寻找替代/更新多行回声的解决方案。

因此,我想与大家分享一个例子。以下脚本在CentOS系统上进行了尝试,并使用了“ timedatectl”命令,该命令基本上可以打印出系统的一些详细时间信息。

我决定使用该命令,因为其输出包含多行,并且可以完美地用于以下示例:

#!/bin/bash
while true; do
  COMMAND=$(timedatectl) #Save command result in a var.
  echo "$COMMAND" #Print command result, including new lines.

  sleep 3 #Keep above's output on screen during 3 seconds before clearing it

  #Following code clears previously printed lines
  LINES=$(echo "$COMMAND" | wc -l) #Calculate number of lines for the output previously printed
  for (( i=1; i <= $(($LINES)); i++ ));do #For each line printed as a result of "timedatectl"
    tput cuu1 #Move cursor up by one line
    tput el #Clear the line
  done

done

上面的代码将timedatectl永远打印“ ” 的结果,并将更新的结果替换为先前的回显。

我不得不提到,此代码仅是示例,但根据您的需求,也许不是最佳的解决方案。一个类似的命令(至少在视觉上)几乎可以做到相同的命令是“ watch -n 3 timedatectl”。

但这是一个不同的故事。:)

希望有帮助!


3

这很有用,请尝试并根据需要进行更改。

#! bin/bash
for load in $(seq 1 100); do
    echo -ne "$load % downloded ...\r"
    sleep 1
done
echo "100"
echo "Loaded ..."

3

您可以尝试一下..我自己的版本..

funcc() {
while true ; do 
for i in \| \/ \- \\ \| \/ \- \\; do 
  echo -n -e "\r$1  $i  "
sleep 0.5
done  
#echo -e "\r                                                                                      "
[ -f /tmp/print-stat ] && break 2
done
}

funcc "Checking Kubectl" & &>/dev/null
sleep 5
touch /tmp/print-stat
echo -e "\rPrint Success                  "

1

我最喜欢的方式称为将睡眠增加到50。这里的i变量需要在echo语句中使用。

for i in $(seq 1 50); do
  echo -ne "$i%\033[0K\r"
  sleep 50
done
echo "ended"

很好,但是光标遮盖了第一个字符。我想回声中的一些空格可以绕开它。
马拉松赛
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.