Cara menampilkan dan memperbarui gema di baris yang sama

112

Saya memiliki yang berikut di Bash (Di 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

Tapi saya ingin membuatnya sehingga "echo" menunjukkan echo berikut pada baris berikutnya (Tidak digabungkan dengan output echo terakhir tetapi menggantinya) sehingga membuatnya terlihat seperti sedang diupdate. Mirip dengan bagaimana bilah kemajuan dengan persen akan ditampilkan pada baris yang sama.

Luis Alvarado
sumber

Jawaban:

196

Yah saya tidak membaca dengan benar man echohalaman untuk ini.

echo memiliki 2 opsi yang dapat melakukan ini jika saya menambahkan karakter escape ke-3.

2 opsi tersebut adalah -ndan -e.

-ntidak akan menampilkan baris baru tambahan. Sehingga saya tidak perlu berpindah ke baris baru setiap kali saya menggemakan sesuatu.

-e akan memungkinkan saya untuk menafsirkan simbol escape dengan garis miring terbalik.

Tebak apa simbol melarikan diri Saya ingin menggunakan untuk ini: \r. Ya, pengembalian kereta akan mengirim saya kembali ke awal dan secara visual akan terlihat seperti saya memperbarui pada baris yang sama.

Jadi garis gema akan terlihat seperti ini:

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

Saya harus melarikan diri dari simbol pelarian agar Bash tidak membunuhnya. itulah mengapa Anda melihat 2 \simbol di sana.

Seperti yang disebutkan oleh William, printfjuga dapat melakukan tugas serupa (dan bahkan lebih ekstensif) seperti ini.

Luis Alvarado
sumber
12
Sekadar catatan untuk masa depan: printf akan melakukan hal yang persis sama, tanpa opsi apa pun. Keuntungannya adalah printf umumnya berperilaku serupa di setiap lingkungan dan OS, sementara echo terkadang berperilaku sangat berbeda. Untuk skrip lintas platform (atau jika Anda pikir Anda mungkin peduli tentang itu), menggunakan printf adalah praktik terbaik.
William T Froggard
8
printf a; printf bkeluaran ab--- printf a\\r; printf bkeluaran b--- printf a\\r; sleep 1; printf bkeluaran a, kemudianb
XavierStuvw
64

Jika saya sudah mengerti dengan baik, Anda bisa mendapatkannya dengan mengganti echo Anda dengan baris berikut:

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

Berikut adalah contoh kecil yang dapat Anda jalankan untuk memahami perilakunya:

#!/bin/bash
for pc in $(seq 1 100); do
    echo -ne "$pc%\033[0K\r"
    sleep 1
done
echo
arutaku
sumber
Tampaknya pada zsh Kitu tidak perlu dan ternyata dikeluarkan seperti huruf K.
mknaf
1
Contoh yang bagus - bagi saya hash bang di awal adalah kuncinya
Felix Eve
22

Jawaban lainnya cukup bagus, tetapi hanya ingin menambahkan beberapa informasi tambahan jika seseorang datang ke sini mencari solusi untuk mengganti / memperbarui gema multiline.

Jadi saya ingin berbagi contoh dengan Anda semua. Skrip berikut telah dicoba pada sistem CentOS dan menggunakan perintah "timedatectl" yang pada dasarnya mencetak beberapa informasi waktu rinci dari sistem Anda.

Saya memutuskan untuk menggunakan perintah itu karena outputnya berisi banyak baris dan berfungsi dengan sempurna untuk contoh di bawah ini:

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

Di atas akan mencetak hasil " timedatectl" selamanya dan akan menggantikan gema sebelumnya dengan hasil yang diperbarui.

Saya harus menyebutkan bahwa kode ini hanya sebuah contoh, tetapi mungkin bukan solusi terbaik untuk Anda tergantung pada kebutuhan Anda. Perintah serupa yang melakukan hal yang hampir sama (setidaknya secara visual) adalah " watch -n 3 timedatectl".

Tapi itu cerita yang berbeda. :)

Semoga membantu!

Antony Fuentes Artavia
sumber
3

Ini sangat berguna, silakan coba dan ubah sesuai kebutuhan.

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

Anda dapat mencoba ini .. Versi saya sendiri ..

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                  "
Raghu K
sumber
1

Cara favorit saya disebut do the sleep to 50. di sini ivariabel perlu digunakan di dalam pernyataan echo.

for i in $(seq 1 50); do
  echo -ne "$i%\033[0K\r"
  sleep 50
done
echo "ended"
Stphane
sumber
ini bagus, tetapi kursor mengaburkan karakter pertama. Saya kira beberapa ruang dalam gema bisa menyiasatinya.
maraton