Як показати та оновити відлуння на одній лінії


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

Але я хочу зробити так, щоб "ехо" показало наступне відлуння в наступному рядку (не поєднуйтесь з останнім результатом ехо, але замініть його), щоб зробити його схожим на оновлення. Подібно до того, як на тому ж рядку відображатиметься смуга прогресу зі відсотками.

Відповіді:


196

Добре, що я для цього неправильно не прочитав man echoсторінку.

echo мав 2 варіанти, які могли б зробити це, якщо я додав третій символ втечі.

2 варіанти є -nі -e.

-nне буде виводити останній новий рядок. Отже, це рятує мене від переходу на новий рядок кожного разу, коли я щось повторюю.

-e дозволить мені інтерпретувати символи втечі зворотної косої риски.

Вгадайте , що втеча символ я хочу використовувати для цього: \r. Так, повернення вагона поверне мене на початок, і це буде візуально виглядати так, що я оновлююсь на тій же лінії.

Отже лінія відлуння виглядала б так:

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

Мені довелося уникнути символу втечі, щоб Баш не вбив його. тому ви бачите там два \символи.

Як згадував Вільям, printfтакож можна виконувати подібні (і навіть більш масштабні) завдання, як це.


12
Лише замітка на майбутнє: printf зробить точно те саме, без жодних варіантів. Перевагою є те, що printf зазвичай поводиться однаково у будь-якому середовищі та ОС, тоді як ехо іноді може поводитись дуже по-різному. Для сценаріїв міжплатформних ситуацій (або якщо ви думаєте, що вам це може хвилюватись), використання printf є найкращою практикою.
Вільям Т Фроггард

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змінну потрібно використовувати всередині висловлювань ехо.

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

це добре, але курсор затемнює перший символ. Я здогадуюсь, що деякі простори в ехо можуть це обійти.
марафон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.