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.

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.


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

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!


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 ..."

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                  "

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"

ini bagus, tetapi kursor mengaburkan karakter pertama. Saya kira beberapa ruang dalam gema bisa menyiasatinya.
maraton
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.