Saat membuat skrip dalam bash atau shell lain di * NIX, saat menjalankan perintah yang akan memakan waktu lebih dari beberapa detik, bilah kemajuan diperlukan.
Misalnya, menyalin file besar, membuka file tar besar.
Cara apa yang Anda rekomendasikan untuk menambahkan progress bar ke skrip shell?
Jawaban:
Anda dapat menerapkan ini dengan menimpa garis. Gunakan
\r
untuk kembali ke awal baris tanpa menulis\n
ke terminal.Tulis
\n
ketika Anda sudah selesai untuk memajukan garis.Gunakan
echo -ne
untuk:\n
dan\r
.Ini demo:
Dalam komentar di bawah ini, puk menyebutkan ini "gagal" jika Anda mulai dengan garis panjang dan kemudian ingin menulis garis pendek: Dalam hal ini, Anda harus menimpa panjang garis panjang (misalnya, dengan spasi).
sumber
printf
bukanecho
.printf "#### (50%%)\r"
itu tidak akan bekerja dengan tanda kutip tunggal dan tanda persen perlu diloloskan.Anda juga mungkin tertarik dengan cara melakukan pemintal :
Bisakah saya melakukan pemintal di Bash?
sumber
while :;do for s in / - \\ \|; do printf "\r$s";sleep .1;done;done
(*:sleep
mungkin memerlukan int daripada desimal)some_work ...
baris di atas; diskusi yang lebih terperinci yang dibangun berdasarkan jawaban yang bermanfaat ini dan komentar Adam Katz yang bermanfaat - dengan fokus pada kepatuhan POSIX - dapat ditemukan di sini .\b
daripada\r
, karena selain itu hanya akan bekerja pada awal baris:while :; do for c in / - \\ \|; do printf '%s\b' "$c"; sleep 1; done; done
- atau, jika menampilkan kursor di belakang pemintal tidak diinginkan:printf ' ' && while :; do for c in / - \\ \|; do printf '\b%s' "$c"; sleep 1; done; done
job=$!
) dan kemudian jalankanwhile kill -0 $job 2>/dev/null;do …
, misalnya:sleep 15 & job=$!; while kill -0 $job 2>/dev/null; do for s in / - \\ \|; do printf "\r$s"; sleep .1; done; done
Beberapa posting telah menunjukkan cara menampilkan progres perintah. Untuk menghitungnya, Anda harus melihat seberapa banyak kemajuan Anda. Pada sistem BSD beberapa perintah, seperti dd (1), menerima
SIGINFO
sinyal, dan akan melaporkan progresnya. Pada sistem Linux, beberapa perintah akan merespons serupaSIGUSR1
. Jika fasilitas ini tersedia, Anda dapat mengirim masukan melalui Andadd
mengirimkan untuk memantau jumlah byte yang diproses.Atau, Anda dapat menggunakan
lsof
untuk mendapatkan offset dari pointer baca file, dan dengan demikian menghitung progresnya. Saya telah menulis sebuah perintah, bernama pmonitor , yang menampilkan progres pemrosesan suatu proses atau file yang ditentukan. Dengannya Anda bisa melakukan hal-hal, seperti berikut ini.Versi skrip shell Linux dan FreeBSD yang lebih lama muncul di blog saya .
sumber
awk
dimainkan!Mendapat fungsi progress bar yang mudah yang saya tulis di hari lain:
Atau ambil dari,
https://github.com/fearside/ProgressBar/
sumber
printf "\rProgress : [${_fill// /▇}${_empty// / }] ${_progress}%%"
gunakan perintah linux pv:
http://linux.die.net/man/1/pv
ia tidak tahu ukurannya jika berada di tengah-tengah sungai, tetapi ia memberikan kecepatan dan total dan dari sana Anda dapat mengetahui berapa lama waktu yang diperlukan dan mendapatkan umpan balik sehingga Anda tahu itu tidak menggantung.
sumber
Saya mencari sesuatu yang lebih seksi daripada jawaban yang dipilih, begitu juga skrip saya sendiri.
Pratinjau
Sumber
Saya menaruhnya di github
progress-bar.sh
Pemakaian
sumber
progress-bar 100
GNU tar memiliki opsi berguna yang memberikan fungsionalitas bilah kemajuan sederhana.
(...) Tindakan pos pemeriksaan lain yang tersedia adalah 'titik' (atau '.'). Ini menginstruksikan tar untuk mencetak satu titik pada aliran daftar standar, misalnya:
Efek yang sama dapat diperoleh dengan:
sumber
--checkpoint=.10
. Ini juga berfungsi baik ketika mengekstraksi dengantar -xz
.Metode yang lebih sederhana yang bekerja pada sistem saya menggunakan utilitas pipeview (pv).
sumber
Belum pernah melihat yang serupa dan semua fungsi khusus di sini tampaknya fokus pada rendering saja jadi ... solusi patuh POSIX saya yang sangat sederhana di bawah ini dengan penjelasan langkah demi langkah karena pertanyaan ini tidak sepele.
TL; DR
Rendering progress bar sangat mudah. Memperkirakan berapa banyak yang harus disajikan adalah masalah yang berbeda. Ini adalah cara merender (menghidupkan) bilah kemajuan - Anda dapat menyalin & menempelkan contoh ini ke file dan menjalankannya:
{1..20}
- nilai dari 1 hingga 20echo -n
- cetak tanpa garis baru di akhirecho -e
- menafsirkan karakter khusus saat mencetak"\r"
- carriage return, char khusus untuk kembali ke awal barisAnda dapat membuatnya menyajikan konten apa pun dengan kecepatan apa pun sehingga metode ini sangat universal, misalnya sering digunakan untuk visualisasi "peretasan" dalam film konyol, tanpa bercanda.
Jawaban penuh
Daging masalahnya adalah bagaimana menentukan
$i
nilai, yaitu berapa banyak progress bar untuk ditampilkan. Dalam contoh di atas saya hanya membiarkannya bertambah dalamfor
lingkaran untuk menggambarkan prinsip tetapi aplikasi kehidupan nyata akan menggunakan loop tak terbatas dan menghitung$i
variabel pada setiap iterasi. Untuk membuat perhitungan tersebut diperlukan bahan-bahan berikut:Dalam kasus
cp
itu perlu ukuran file sumber dan ukuran file target:stat
- periksa statistik file-c
- mengembalikan nilai yang diformat%s
- ukuran totalDalam hal operasi seperti membongkar file, menghitung ukuran sumber sedikit lebih sulit tetapi masih semudah mendapatkan ukuran file yang tidak terkompresi:
gzip -l
- Menampilkan info tentang arsip ziptail -n1
- bekerja dengan 1 baris dari bawahtr -s ' '
- menerjemahkan beberapa spasi menjadi satu (tekan)cut -d' ' -f3
- potong kolom ke-3 yang dibatasi ruangTapi inilah masalahnya. Solusi ini semakin tidak umum. Semua perhitungan kemajuan aktual terikat erat dengan domain yang Anda coba visualisasikan, apakah itu operasi file tunggal, penghitung waktu mundur, peningkatan jumlah file dalam direktori, operasi pada banyak file, dll., Oleh karena itu, tidak bisa digunakan kembali. Satu-satunya bagian yang dapat digunakan kembali adalah rendering progress bar. Untuk menggunakannya kembali, Anda perlu mengabstraksikan dan menyimpannya dalam file (mis.
/usr/lib/progress_bar.sh
), Lalu mendefinisikan fungsi yang menghitung nilai input khusus untuk domain Anda. Beginilah tampilan kode yang digeneralisasi (saya juga membuat$BAR
dinamis karena orang memintanya, sisanya harus jelas sekarang):printf
- bawaan untuk mencetak barang dalam format yang diberikanprintf '%50s'
- cetak apa-apa, pad dengan 50 spasitr ' ' '#'
- menerjemahkan setiap spasi menjadi tanda pagarDan inilah cara Anda menggunakannya:
Jelas itu dapat dibungkus dalam suatu fungsi, ditulis ulang untuk bekerja dengan aliran pipa, ditulis ulang ke bahasa lain, apa pun racun Anda.
sumber
Saya juga ingin berkontribusi pada progress bar saya sendiri
Ini mencapai presisi sub-karakter dengan menggunakan setengah blok unicode
Kode sudah termasuk
sumber
Bilah progres gaya APT (Tidak merusak output normal)
EDIT: Untuk versi yang diperbarui periksa halaman github saya
Saya tidak puas dengan jawaban atas pertanyaan ini. Apa yang saya cari secara pribadi adalah bilah kemajuan mewah seperti yang terlihat oleh APT.
Saya telah melihat kode sumber C untuk APT dan memutuskan untuk menulis padanan saya sendiri untuk bash.
Baris kemajuan ini akan tetap baik di bagian bawah terminal dan tidak akan mengganggu output yang dikirim ke terminal.
Harap perhatikan bahwa bilah saat ini diperbaiki dengan lebar 100 karakter. Jika Anda ingin mengaturnya dengan ukuran terminal, ini juga cukup mudah untuk dilakukan (Versi yang diperbarui pada halaman github saya juga menangani ini).
Saya akan memposting skrip saya di sini. Contoh penggunaan:
Script (Saya sangat merekomendasikan versi di github saya sebagai gantinya):
sumber
Ini memungkinkan Anda memvisualisasikan bahwa suatu perintah masih dijalankan:
Ini akan membuat loop tak terbatas sementara yang dijalankan di latar belakang dan menggandakan "." setiap detik. Ini akan ditampilkan
.
di shell. Jalankantar
perintah atau perintah yang Anda inginkan. Ketika perintah itu selesai dieksekusi kemudian bunuh pekerjaan terakhir yang berjalan di latar belakang - yang merupakan loop sementara tak terbatas .sumber
Berikut ini tampilannya
Mengunggah file
Menunggu pekerjaan selesai
Fungsi sederhana yang mengimplementasikannya
Anda cukup menyalin-menempelnya ke skrip Anda. Tidak memerlukan hal lain untuk bekerja.
Contoh penggunaan
Di sini, kami mengunggah file dan menggambar ulang bilah kemajuan di setiap iterasi. Tidak masalah pekerjaan apa yang sebenarnya dilakukan selama kita bisa mendapatkan 2 nilai: nilai maks dan nilai saat ini.
Dalam contoh di bawah ini nilai maks adalah
file_size
dan nilai saat ini disediakan oleh beberapa fungsi dan dipanggiluploaded_bytes
.sumber
Sebagian besar perintah unix tidak akan memberi Anda semacam umpan balik langsung dari mana Anda bisa melakukan ini. Beberapa akan memberi Anda output pada stdout atau stderr yang dapat Anda gunakan.
Untuk sesuatu seperti tar, Anda bisa menggunakan -v switch dan menyalurkan output ke program yang memperbarui animasi kecil untuk setiap baris yang dibacanya. Sebagai tar menulis daftar file itu terurai program dapat memperbarui animasi. Untuk menyelesaikan satu persen, Anda harus mengetahui jumlah file dan menghitung baris.
cp tidak memberikan output semacam ini sejauh yang saya tahu. Untuk memantau perkembangan cp, Anda harus memantau sumber dan tujuan file dan melihat ukuran tujuan. Anda bisa menulis program c kecil menggunakan panggilan sistem stat (2) untuk mendapatkan ukuran file. Ini akan membaca ukuran sumber kemudian polling file tujuan dan memperbarui bar% lengkap berdasarkan ukuran file yang ditulis hingga saat ini.
sumber
Solusi saya menampilkan persentase tarball yang saat ini sedang dikompresi dan ditulis. Saya menggunakan ini saat menulis gambar filesystem root 2GB. Anda benar-benar membutuhkan bilah kemajuan untuk hal-hal ini. Apa yang saya lakukan adalah menggunakan
gzip --list
untuk mendapatkan ukuran tarball yang tidak terkompresi. Dari itu saya menghitung faktor pemblokiran yang diperlukan untuk membagi file menjadi 100 bagian. Akhirnya, saya mencetak pesan pos pemeriksaan untuk setiap blok. Untuk file 2GB ini memberikan sekitar 10MB blok. Jika itu terlalu besar maka Anda dapat membagi BLOCKING_FACTOR dengan 10 atau 100, tetapi kemudian lebih sulit untuk mencetak hasil yang cantik dalam hal persentase.Dengan asumsi Anda menggunakan Bash maka Anda dapat menggunakan fungsi shell berikut
sumber
Pertama-tama bar bukan satu-satunya meteran progres pipa. Yang lain (mungkin bahkan lebih dikenal) adalah pv (penampil pipa).
Bilah dan pv kedua dapat digunakan misalnya seperti ini:
atau bahkan:
salah satu trik yang berguna jika Anda ingin menggunakan bar dan pv dalam perintah yang bekerja dengan file yang diberikan dalam argumen, seperti misalnya salin file1 file2, adalah dengan menggunakan proses substitusi :
Substitusi proses adalah hal bash magic yang membuat file pipa fifo sementara / dev / fd / dan menghubungkan stdout dari proses yang dijalankan (di dalam tanda kurung) melalui pipa ini dan menyalin melihatnya seperti file biasa (dengan satu pengecualian, hanya dapat membacanya ke depan).
Memperbarui:
perintah bar itu sendiri memungkinkan juga untuk menyalin. Setelah bar pria:
Tetapi proses substitusi menurut saya merupakan cara yang lebih umum untuk melakukannya. Itu menggunakan program cp itu sendiri.
sumber
Saya lebih suka menggunakan dialog dengan param --gauge . Sangat sering digunakan dalam instalasi paket deb dan hal-hal konfigurasi dasar lainnya dari banyak distro. Jadi, Anda tidak perlu menemukan kembali roda ... lagi
Masukkan nilai int dari 1 hingga 100 @stdin. Satu contoh dasar dan konyol:
Saya memiliki file / bin / Tunggu ini (dengan chmod u + x perms) untuk keperluan memasak: P
Jadi saya bisa meletakkan:
Wait "34 min" "warm up the oven"
atau
Wait "dec 31" "happy new year"
sumber
bagi saya yang paling mudah digunakan dan yang paling baik dilihat sejauh ini adalah perintah
pv
ataubar
seperti yang sudah ditulis oleh beberapa orangmisalnya: perlu membuat cadangan seluruh drive dengan
dd
biasanya Anda gunakan
dd if="$input_drive_path" of="$output_file_path"
dengan
pv
Anda dapat membuatnya seperti ini:dd if="$input_drive_path" | pv | dd of="$output_file_path"
dan progresnya langsung
STDOUT
seperti ini:setelah selesai ringkasan muncul
sumber
pv
ataubar
untuk memvisualisasikan kemajuan proses yang berbeda, misalnya penghitung waktu mundur, posisi dalam file teks, instalasi aplikasi Anda, pengaturan runtime, dll.?Banyak jawaban menjelaskan menulis perintah Anda sendiri untuk dicetak
'\r' + $some_sort_of_progress_msg
. Masalahnya kadang-kadang adalah bahwa mencetak ratusan pembaruan ini per detik akan memperlambat proses.Namun, jika ada proses Anda menghasilkan output (misalnya
7z a -r newZipFile myFolder
akan menampilkan setiap nama file saat dikompres) maka ada solusi yang lebih sederhana, cepat, tidak menyakitkan dan dapat disesuaikan.Instal modul python
tqdm
.Bantuan:
tqdm -h
. Contoh menggunakan lebih banyak opsi:Sebagai bonus, Anda juga dapat menggunakan
tqdm
untuk membungkus iterables dalam kode python.https://github.com/tqdm/tqdm/blob/master/README.rst#module
sumber
tqdm
STDOUTwc -l
melalui pipa. Anda mungkin ingin menghindarinya.tqdm
akan menunjukkan kemajuanSTDERR
saat memasukkan inputnyaSTDIN
keSTDOUT
. Dalam hal ini,wc -l
siapa yang akan menerima input yang sama seolah-olahtqdm
tidak dimasukkan.Berdasarkan karya Edouard Lopez, saya membuat progress bar yang sesuai dengan ukuran layar, apa pun itu. Coba lihat.
Ini juga diposting di Git Hub .
Nikmati
sumber
https://github.com/extensionsapp/progre.sh
Buat kemajuan 40 persen:
progreSh 40
sumber
Ini hanya berlaku menggunakan gnome zenity. Zenity menyediakan antarmuka asli yang bagus untuk skrip bash: https://help.gnome.org/users/zenity/stable/
Dari Contoh Zenity Progress Bar:
sumber
Saya menggunakan jawaban dari Membuat string karakter yang diulang dalam skrip shell untuk pengulangan char. Saya memiliki dua versi bash yang relatif kecil untuk skrip yang perlu menampilkan progress bar (misalnya, loop yang melewati banyak file, tetapi tidak berguna untuk file tar besar atau operasi salin). Yang lebih cepat terdiri dari dua fungsi, satu untuk menyiapkan string untuk tampilan bar:
dan satu untuk menampilkan bilah kemajuan:
Ini dapat digunakan sebagai:
yang berarti menyiapkan string untuk bilah dengan 50 "#" karakter, dan setelah itu:
akan menampilkan jumlah karakter "#" yang sesuai dengan rasio 35/80:
Ketahuilah bahwa fungsi menampilkan bilah pada baris yang sama berulang-ulang sampai Anda (atau program lain) mencetak baris baru. Jika Anda menempatkan -1 sebagai parameter pertama, bilah akan dihapus:
Versi lebih lambat semuanya dalam satu fungsi:
dan itu dapat digunakan sebagai (contoh yang sama seperti di atas):
Jika Anda memerlukan progressbar pada stderr, tambahkan saja
>&2
di akhir setiap perintah printf.sumber
Untuk menunjukkan kemajuan aktivitas, coba perintah berikut:
ATAU
ATAU
ATAU
Seseorang dapat menggunakan flag / variabel di dalam loop sementara untuk memeriksa dan menampilkan nilai / tingkat kemajuan.
sumber
Menggunakan saran yang tercantum di atas, saya memutuskan untuk menerapkan bilah kemajuan saya sendiri.
sumber
percent_none="$(( 100 - "$percent_done" ))"
kepercent_none="$(( 100 - $percent_done))"
Saya melakukan versi shell murni untuk sistem embedded mengambil keuntungan dari:
Fitur penanganan sinyal SIGUSR1 / usr / bin / dd.
Pada dasarnya, jika Anda mengirim 'kill SIGUSR1 $ (pid_of_running_dd_process)', itu akan menampilkan ringkasan kecepatan dan jumlah throughput yang ditransfer.
backgrounding dd dan kemudian meminta secara teratur untuk pembaruan, dan menghasilkan kutu hash seperti dulu ftp klien.
Menggunakan / dev / stdout sebagai tujuan untuk program ramah non-stdout seperti scp
Hasil akhirnya memungkinkan Anda untuk mengambil operasi transfer file apa pun dan mendapatkan pembaruan kemajuan yang terlihat seperti keluaran 'hash' FTP sekolah lama di mana Anda hanya akan mendapatkan tanda pagar untuk setiap X byte.
Ini bukan kode kualitas produksi, tetapi Anda mendapatkan idenya. Saya pikir itu lucu.
Untuk apa nilainya, byte-count yang sebenarnya mungkin tidak tercermin dengan benar dalam jumlah hash - Anda mungkin memiliki satu lebih atau kurang tergantung pada masalah pembulatan. Jangan gunakan ini sebagai bagian dari skrip tes, itu hanya eye-candy. Dan, ya, saya sadar ini sangat tidak efisien - ini adalah shell script dan saya tidak meminta maaf untuk itu.
Contoh dengan wget, scp dan tftp disediakan di akhir. Ini harus bekerja dengan apa pun yang memancarkan data. Pastikan untuk menggunakan / dev / stdout untuk program yang tidak ramah stdout.
Contoh:
sumber
pidof dd
itu menakutkan.$!
daridd
dan menunggu[[ -e /proc/${DD_PID} ]]
.Jika Anda harus menunjukkan bilah kemajuan temporal (dengan mengetahui sebelumnya waktu yang ditampilkan), Anda dapat menggunakan Python sebagai berikut:
Kemudian, dengan asumsi Anda menyimpan skrip Python sebagai
progressbar.py
, dimungkinkan untuk menampilkan bilah progres dari skrip bash Anda dengan menjalankan perintah berikut:Itu akan menampilkan
50
karakter ukuran bar kemajuan dan "berjalan" selama beberapa10
detik.sumber
Saya telah membangun jawaban yang diberikan oleh sisi ketakutan
Ini terhubung ke database Oracle untuk mengambil progres pengembalian RMAN.
sumber
dapat membuat fungsi yang menggambar ini pada skala katakanlah 1-10 untuk jumlah bar:
sumber
keluaran:
Catatan: jika alih-alih 255 Anda meletakkan 1 Anda akan memantau standar dalam ... dengan 2 standar keluar (tetapi Anda harus memodifikasi sumber untuk menetapkan "tot" ke ukuran file output yang diproyeksikan)
sumber