Как показать и обновить эхо на одной строке
У меня есть следующее в 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
Но я хочу сделать так, чтобы "эхо" отображало следующее эхо на следующей строке (не конкатенация с последним выходом эха, а замена его), чтобы он выглядел так, как будто он обновляется. Аналогично тому, как индикатор выполнения с процентом будет отображаться в одной строке.
Ответы
Ответ 1
Ну, я не правильно прочитал страницу man echo
для этого.
В echo было 2 варианта, которые могли бы сделать это, если бы я добавил третий escape-символ.
2 варианта: -n
и -e
.
-n
не выводит конечную новую строку. Так что это спасает меня от перехода на новую строку каждый раз, когда я что-то повторяю.
-e
позволит мне интерпретировать символы обратного слэша.
Угадайте, какой escape-символ я хочу использовать для этого: \r
. Да, возврат каретки вернет меня к началу, и он будет визуально выглядеть так, как будто я обновляюсь в той же строке.
Итак, эхо-строка будет выглядеть так:
echo -ne "Movie $movies - $dir ADDED!"\\r
Мне пришлось сбежать из escape-символа, поэтому Bash не убьет его. поэтому вы видите там 2 \
.
Как упоминалось Уильямом, printf
также может выполнять аналогичные (и даже более обширные) задачи, подобные этому.
Ответ 2
Если я хорошо понял, вы можете заставить его заменить ваше эхо на следующую строку:
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
Ответ 3
Остальные ответы довольно хороши, но я просто хотел добавить дополнительную информацию на случай, если кто-то придет сюда в поисках решения для замены/обновления многострочного эха.
Поэтому я хотел бы поделиться примером со всеми вами. Следующий скрипт был опробован в системе 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 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
".
Но это другая история. :)
Надеюсь, это поможет!
Ответ 4
Это полезно, пожалуйста, попробуйте и измените по мере необходимости.
#! bin/bash
for load in $(seq 1 100); do
echo -ne "$load % downloded ...\r"
sleep 1
done
echo "100"
echo "Loaded ..."
Ответ 5
Мой любимый способ называется do sleep to 50. здесь i
должен использовать переменную внутри операторов echo.
for i in $(seq 1 50); do
echo -ne "$i%\033[0K\r"
sleep 50
done
echo "ended"
Ответ 6
Вы можете попробовать это.. Моя собственная версия этого..
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 "