Bash'da bir ilerleme çubuğu oluşturma


14

Bash ile nasıl bir ilerleme çubuğu oluşturabilirim?

Bu benim senaryom:

 #!/bin/bash
 pass='number1 number12 number13 number14 number15 number16'
 chk='number14'
 for i in $pass ; do
 if [ "$i" == "$chk" ]; then
 echo ' Found ^_^'
 else
 echo 'loading 50%'
 fi
 done

echo 'loading 50%'Bir ilerleme çubuğu oluşturmak için herhangi bir şeyle değiştirmek istiyorum .


1
Terminaldeki bir ilerleme çubuğu veya ayrı bir GUI penceresinde bir ilerleme çubuğu?
Bayt Komutanı

2
Terminalde
Black Hawk

etaNe istediğinizi yapabilir.
aioobe

Yanıtlar:


14

whiptail Ubuntu ve diğer birçok dağıtımda önceden yüklenmiş olarak gelir ve tam ekran (ancak yine de terminal tabanlı) ilerleme öğelerini gösterir.

dialogbir üst kümedir whiptail, bu nedenle bu örnek her ikisiyle de eşit derecede iyi çalışır. Daha gelişmiş UI öğeleri sağlar, bu nedenle dosya seçiciler ve formlar gibi kullanıcı etkileşimi arıyorsanız kullanışlı olabilir, ancak birçok sisteme önceden yüklenmemiş olması dezavantajına sahiptir.

whiptail

diyalog

for i in $(seq 1 100)
do
    sleep 0.1 
    echo $i
done | whiptail --title 'Test script' --gauge 'Running...' 6 60 0

Komut dosyası çıktısının yüzde olarak yorumlandığını unutmayın, bu nedenle çıktılarınızı buna göre ayarlamanız gerekebilir.

Whiptail ve Dialog ayrıca metni çalışma zamanında oldukça şifreli bir sözdizimi ile değiştirmenize izin verir:

phases=( 
    'Locating Jebediah Kerman...'
    'Motivating Kerbals...'
    'Treating Kessler Syndrome...'
    'Recruiting Kerbals...'
)   

for i in $(seq 1 100); do  
    sleep 0.1

    if [ $i -eq 100 ]; then
        echo -e "XXX\n100\nDone!\nXXX"
    elif [ $(($i % 25)) -eq 0 ]; then
        let "phase = $i / 25"
        echo -e "XXX\n$i\n${phases[phase]}\nXXX"
    else
        echo $i
    fi 
done | whiptail --title 'Kerbal Space Program' --gauge "${phases[0]}" 6 60 0

pvbir dosya veya akışın üzerinden aktarılan ilerlemeyi gösterir. Ancak, döngü gibi özel bir işlemin ilerlemesini göstermek için (kolayca?) Kullanılamaz. Özellikle akışlar için tasarlanmıştır.

$ head -c 1G < /dev/urandom | pv -s 1G > /dev/null
 277MB 0:00:16 [17.4MB/s] [========>                           ] 27% ETA 0:00:43

pvKullanışlı olduğu bazı gerçek dünya örnekleri :

# progress while importing a DB dump
pv mybigfile.sql | mysql -uroot -p dbname

# importing straight from a remote server
ssh user@server 'cat mybigfile.sql.gz' | pv | gzip -cd | mysql -uroot -p dbname

# taking a snapshot of a btrfs partition
btrfs send /snapshots/$date | pv | btrfs receive /mnt/backup/root

Tek satırlı ilerleme çubuklarını pvveya stilinde veren herhangi bir komut bilmiyorum wget, ancak diğerleri burada paylaştığı gibi bu işlevi ekleyecek çok sayıda basit Bash / Perl / sed komut dosyası var.


Bir döngünün sürecini göstermek pviçin, döngünün çıktısını aramasını sağlayabilir veya örneğin echoher yinelemede bir sahte çıkış oluşturabilir, pvbunu birbirine bağlayabilir ve yineleme sayısını verebilirsiniz -s. İstenmezse, döngünün stdout'unu yeniden yönlendirmeyi unutmayın /dev/null. İşte bu yaklaşımı gösteren bir örnek .
tatlı

6

zenityBasit GTK iletişim pencereleri oluşturmak için kullanabilirsiniz . Mevcut seçeneklerden biri bir ilerleme çubuğu iletişim kutusudur.

Kullanarak böyle bir pencere oluşturun zenity --progress. Yararlı hale getirmek için aşağıdaki seçeneklerden bazılarını ekleyerek daha fazla bilgi belirtmelisiniz (alıntı man zenity):

   Progress options
   --text=STRING
          Set the dialog text
   --percentage=INT
          Set initial percentage
   --auto-close
          Close dialog when 100% has been reached
   --auto-kill
          Kill parent process if cancel button is pressed
   --pulsate
          Pulsate progress bar
   --no-cancel
          Hides the cancel button

İki mod vardır:

  • titreşen : İlerleme çubuğu titreşen, sadece bir şeyin çalıştığını gösterir, ancak ilerleme hakkında hiçbir şey söylemez. Bunu --pulsatingseçeneği belirleyerek yaparsınız .

  • manual : zenityİlerleme çubuğunu güncellemek için geçerli ilerleme yüzdesini komutun standart girdisine yönlendirmeniz gerekir.
    Bunun bir örneği aşağıdaki gibi görünebilir. Önceki komutların, zenityyalnızca son komutun değil tüm çıktının iletişim kutusuna yönlendirilmesi için bir alt kabuğa gruplandığını unutmayın :

    (echo 10; sleep 2; echo 20; sleep 2; echo 50; sleep 2) | zenity --progress

Bu da bir seçenek olabilir.
Bayt Komutanı

1
Üzgünüm canım, bu GUI ilerleme çubuğu pencereler, ben terminalde bir ilerleme çubuğu oluşturmak istiyorum, örneğin ben komut dosyası kontrol ederken görmek istiyorum ==>[ ###########--------------] 52%
Black Hawk

1
Evet anladım. Bunu söylediğin zaman cevabımın yarısını zaten yazmıştım, bu yüzden gelecekte başka birine ihtiyaç duyması ihtimaline karşı yine de göndermeye karar verdim. Umarım umursamazsınız, çünkü birkaç terminal tabanlı çözüm de vardır.
Bayt Komutanı

5

Bu kod bunu yapacak ve hiçbir şey gerektirmiyor (elbette bash dışında). #Yorumunuzda sorduğunuz gibi işaretler yazdırır :

pass='number1 number12 number13 number14 number15 number16'
chk='number14'
passarr=($pass)
lenProgressBar=${#passarr[@]}

echo -n '['
i=0

while [ $i -lt $lenProgressBar ]; do
    echo -n '-'
    ((i++))
done

echo -n ']'
i=0

while [ $i -lt $lenProgressBar ]; do
    echo -e -n '\b'
    ((i++))
done

echo -e -n '\b'
for i in $pass ; do
    if [ "$i" = "$chk" ]; then
        echo -e '#\nFound ^_^'
        break
    else
        echo -n '#'
    fi
done

Ancak, kontrol edilecek çok şeyiniz varsa, bu sadece ekranınızı #işaretlerle dolduracaktır . Bu sorunu gidermek için şu kodu deneyin:

lenProgressBar=5
pass='number1 number12 number13 number14 number15 number16'
chk='number14'
passarr=($pass)
lenPass=${#passarr[@]}

if [ $lenProgressBar -gt $lenPass ]; then
    lenProgressBar=lenPass
elif [ $lenProgressBar -lt 1 ]; then
    lenProgressBar=1
fi

let "chksForEqualsPrint = $lenPass / $lenProgressBar"
echo -n '['
i=0

while [ $i -lt $lenProgressBar ]; do
    echo -n '-'
    ((i++))
done

echo -n ']'
i=0

while [ $i -lt $lenProgressBar ]; do
    echo -e -n '\b'
    ((i++))
done

echo -e -n '\b'
n=1

for i in $pass ; do
    if [ "$i" = "$chk" ]; then
        echo -e '\nFound ^_^'
        break
    else
        if [ $n -eq $chksForEqualsPrint ]; then
            echo -n '#'
            n=1
        else
            ((n++))
        fi
    fi
done

İlk satırdaki ( lenProgressBar=5) 5 sayısını ilerleme çubuğunuzun olmasını istediğiniz uzunlukta değiştirin. Daha uzun #uzunluktaki ilerleme çubuklarına sahip bir işaretin yazdırılması , daha uzun olanlara göre daha uzun sürer, ancak ilerleme çubuğunun uzunluğunun ekran boyutunuzu aşmasına izin vermeyin; eğer yaparsan iyi çalışmaz. (Kontrol ettiğiniz öğe sayısından daha yüksek veya 1'den daha düşük bir ilerleme çubuğu kullanmanıza izin vermez)


1
Bu kullanabilir tput colsuç Pencerenin genişliğini algılar ve buna göre progressbar ölçek.
Mikkel

1

Ansi kaçış kodlarını kullanan başka bir yaklaşım:

#!/bin/bash

pass='number1 number2 number 3 number4 number12 number13 number14 number15 number16'
chk='number15'
result="Not Found!"

echo
echo -n "Working... "
echo -ne "\033[1;32m\033[7m\033[?25l"

for i in $pass ; do
   sleep .4s
   if [ "$i" == "$chk" ]; then
      result="  Found ^_^"
      break
   else
      echo -n " "
   fi
done

echo -ne "\r\033[0m\033[K\033[?25h"
echo $result
echo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.