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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12628327/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 22:45:45  来源:igfitidea点击:

How to show and update echo on same line

bash

提问by Luis Alvarado

I have the following in Bash (In Linux)

我在 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

But I wish to make it so the "echo" shows the following echo on the next line (Not concatenate with the last echo output but replace it) so to make it look like it is updating. Similar to how a progress bar with percent would show on the same line.

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

回答by Luis Alvarado

Well I did not read correctly the man echopage for this.

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

echo had 2 options that could do this if I added a 3rd escape character.

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

The 2 options are -nand -e.

两个选项是-n-e

-nwill not output the trailing newline. So that saves me from going to a new line each time I echo something.

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

-ewill allow me to interpret backslash escape symbols.

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

Guess what escape symbol I want to use for this: \r. Yes, carriage return would send me back to the start and it will visually look like I am updating on the same line.

猜猜我想为此使用什么转义符号:\r. 是的,回车会让我回到开头,它在视觉上看起来就像我在同一行更新。

So the echo line would look like this:

所以回声线看起来像这样:

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

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

I had to escape the escape symbol so Bash would not kill it. that is why you see 2 \symbols in there.

我不得不逃避转义符号,这样 Bash 就不会杀死它。这就是为什么你\在那里看到 2 个符号的原因。

As mentioned by William, printfcan also do similar (and even more extensive) tasks like this.

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

回答by arutaku

If I have understood well, you can get it replacing your echo with the following line:

如果我理解得很好,您可以使用以下行替换您的回声:

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

Here is a small example that you can run to understand its behaviour:

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

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

回答by Antony Fuentes Artavia

The rest of answers are pretty good, but just wanted to add some extra information in case someone comes here looking for a solution to replace/update a multiline echo.

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

So I would like to share an example with you all. The following script was tried on a CentOS system and uses "timedatectl" command which basically prints some detailed time information of your system.

所以我想和大家分享一个例子。以下脚本已在 CentOS 系统上试用,并使用“timedatectl”命令,该命令基本上打印了系统的一些详细时间信息。

I decided to use that command as its output contains multiple lines and works perfectly for the example below:

我决定使用该命令,因为它的输出包含多行并且非常适合下面的示例:

#!/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

The above will print the result of "timedatectl" forever and will replace the previous echo with updated results.

以上将timedatectl永远打印 " "的结果,并将用更新的结果替换之前的 echo。

I have to mention that this code is only an example, but maybe not the best solution for you depending on your needs. A similar command that would do almost the same (at least visually) is "watch -n 3 timedatectl".

我不得不提一下,这段代码只是一个例子,但根据您的需要,它可能不是最适合您的解决方案。执行几乎相同(至少在视觉上)的类似命令是“ watch -n 3 timedatectl”。

But that's a different story. :)

但那是另一回事了。:)

Hope that helps!

希望有帮助!

回答by Mantu

This is vary useful please try it and change as required.

这是非常有用的,请尝试并根据需要进行更改。

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

回答by Raghu K

You can try this.. My own version of it..

你可以试试这个..我自己的版本..

funcc() {
while true ; do 
for i in \| \/ \- \ \| \/ \- \; do 
  echo -n -e "\r  $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                  "

回答by Raghu K

My favorite way is called do the sleep to 50. here ivariable need to be used inside echo statements.

我最喜欢的方法叫做 do the sleep to 50。这里的i变量需要在 echo 语句中使用。

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