144

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

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

4

7 回答 7

243

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

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

2 个选项是-n-e

-n不会输出尾随的换行符。这样一来,每次我回显某些内容时,我就不用换行了。

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

猜猜我想用什么转义符号:\r. 是的,回车会让我回到开头,看起来我在同一行进行更新。

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

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

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

正如威廉所说,printf也可以像这样完成类似(甚至更广泛)的任务。

于 2012-09-27T19:10:14.490 回答
71

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

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
于 2012-09-27T19:11:57.320 回答
30

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

所以我想和大家分享一个例子。以下脚本在 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”。

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

希望有帮助!

于 2016-12-16T19:40:34.317 回答
10

我使用 printf,它更短,因为它不需要标志来完成工作:

printf "\rMy static $myvars composed text"
于 2020-12-29T18:22:08.763 回答
6

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

#!/bin/bash
for load in $(seq 1 100); do
    echo -ne "$load % downloded ...\r"
    sleep 1
done
echo "100"
echo "Loaded ..."
于 2018-02-17T12:50:32.990 回答
4

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

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                  "
于 2019-01-11T09:58:05.680 回答
3

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

for i in $(seq 1 50); do
  echo -ne "$i%\033[0K\r"
  sleep 50
done
echo "ended"
于 2018-01-16T17:49:58.927 回答