बैश में एक प्रगति बार बनाएँ


14

मैं बैश के साथ एक प्रगति बार कैसे बना सकता हूं?

यह मेरी स्क्रिप्ट है:

 #!/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%'प्रगति पट्टी बनाने के लिए किसी भी चीज़ से प्रतिस्थापित करना चाहता हूं ।


1
टर्मिनल में प्रगति पट्टी या अलग GUI विंडो में प्रगति पट्टी?
बाइट कमांडर

2
टर्मिनल में
ब्लैक हॉक

etaतुम क्या चाहते हो सकता है।
aioobe

जवाबों:


14

whiptail उबंटू और कई अन्य डिस्ट्रो पर प्रीइंस्टॉल्ड आता है, और पूर्ण-स्क्रीन (लेकिन अभी भी टर्मिनल-आधारित) प्रगति तत्वों को दिखाएगा।

dialogका सुपरसेट है whiptail, इसलिए यह उदाहरण दोनों के साथ समान रूप से काम करेगा। यह अधिक उन्नत UI तत्व प्रदान करता है, इसलिए यह आपके लिए उपयोगी हो सकता है यदि आप फ़ाइल पिकर और फ़ॉर्म जैसे उपयोगकर्ता इंटरैक्शन की तलाश कर रहे हैं, लेकिन इसके कई प्रणालियों पर पूर्वस्थापित नहीं होने का नुकसान है।

whiptail

संवाद

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

ध्यान दें कि स्क्रिप्ट आउटपुट की व्याख्या प्रतिशत के रूप में की जाती है, इसलिए आपको अपने आउटपुट को तदनुसार समायोजित करना पड़ सकता है।

व्हिपटेल और डायलॉग आपको पाठ को समय-समय पर क्रिप्टि सिंटैक्स के माध्यम से संशोधित करने की अनुमति देते हैं:

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

pvकिसी फ़ाइल या स्ट्रीम की प्रगति को इसके माध्यम से दिखाया जा सकता है। हालांकि यह (आसानी से) एक लूप जैसे कस्टम ऑपरेशन की प्रगति दिखाने के लिए नहीं किया जा सकता है। यह विशेष रूप से धाराओं के लिए डिज़ाइन किया गया है।

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

कुछ वास्तविक दुनिया के उदाहरण जहाँ pvकाम आता है:

# 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

मुझे ऐसी किसी भी कमांड के बारे में नहीं पता है जो pvया की शैली में एक-पंक्ति प्रगति पट्टियाँ देती हो wget, लेकिन इसमें बहुत सी सरल बैश / पर्ल / सीड स्क्रिप्ट हैं जो उस कार्यक्षमता को जोड़ देंगी, जैसा कि अन्य लोगों ने यहाँ साझा किया है।


pvआप के साथ एक लूप की प्रक्रिया को दिखाने के लिए या तो यह लूप के आउटपुट की तलाश कर सकता है या कुछ नकली आउटपुट बना सकता है, जैसे कि echoप्रत्येक पुनरावृत्ति में, इसे पाइप करें pvऔर इसे पुनरावृत्ति गिनती के साथ दें -s। यदि यह नहीं चाहता है, तो लूप के स्टडआउट को पुनर्निर्देशित करना याद रखें /dev/nullइस दृष्टिकोण को दर्शाने वाला एक उदाहरण यहां दिया गया है
मिठाई

6

आप zenityसाधारण GTK संवाद विंडो बनाने के लिए उपयोग कर सकते हैं । उपलब्ध विकल्पों में से एक प्रगति बार संवाद है।

आप ऐसी विंडो का उपयोग करके बनाते हैं zenity --progress। इसे उपयोगी बनाने के लिए, आपको नीचे दिए गए कुछ विकल्पों को जोड़कर अधिक जानकारी निर्दिष्ट करनी चाहिए 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

दो तरीके हैं:

  • स्पंदना : प्रगति पट्टी स्पंदित हो रही है, यह सिर्फ इंगित करता है कि कुछ चल रहा है, लेकिन प्रगति के बारे में कुछ भी नहीं बताता है। आप --pulsatingविकल्प सेट करके ऐसा करते हैं ।

  • मैनुअल : आपको zenityप्रगति बार को अपडेट करने के लिए कमांड के मानक इनपुट पर वर्तमान प्रगति प्रतिशत को पाइप करना होगा।
    इसके लिए एक उदाहरण नीचे ऐसा लग सकता है। ध्यान दें कि पिछले आदेशों को एक उपखंड में समूहीकृत किया गया है ताकि सभी आउटपुट zenityसंवाद पर पुनर्निर्देशित हो जाएं और न केवल अंतिम चरण में:

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

बस के मामले में यह भी एक विकल्प होगा।
बाइट कमांडर

1
क्षमा करें मेरे प्रिय, यह GUI प्रगति बार खिड़कियां है, मैं टर्मिनल में एक प्रगति बार बनाना चाहता हूं, उदाहरण के लिए मैं इसे देखना चाहता हूं जबकि स्क्रिप्ट जाँच रहा है ==>[ ###########--------------] 52%
ब्लैक हॉक

1
हाँ मैं समझता हूँ। यह सिर्फ इतना है कि जब आपने कहा था कि मैंने अपना आधा जवाब पहले ही लिख दिया है, तो मैंने अभी इसे किसी भी तरह से पोस्ट करने का फैसला किया है अगर भविष्य में किसी और को इसकी आवश्यकता हो सकती है। मुझे आशा है कि आप बुरा नहीं मानेंगे, क्योंकि कुछ टर्मिनल आधारित समाधान भी हैं।
बाइट कमांडर

5

यह कोड इसे करेगा, और इसके अलावा कुछ भी (bash के अलावा) की आवश्यकता नहीं है। यह #संकेत छापता है, जैसे आपने अपनी टिप्पणी में पूछा था:

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

हालाँकि, यदि आपके पास जाँच करने के लिए बहुत कुछ है, तो यह आपकी स्क्रीन को #संकेतों से भर देगा । उस समस्या को ठीक करने के लिए, इस कोड को आज़माएं:

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

पहली पंक्ति में 5 lenProgressBar=5को उस लंबाई में बदलें ( जिसे आप चाहते हैं कि आपकी प्रगति पट्टी हो। #अधिक लंबाई वाले लोगों की तुलना में कम लंबाई की प्रगति पट्टियों के साथ एक चिन्ह प्रिंट करने में अधिक समय लगेगा , लेकिन प्रगति पट्टी की लंबाई को आपके स्क्रीन आकार से अधिक नहीं होने देना चाहिए; यदि आप ऐसा करते हैं तो यह अच्छी तरह से काम नहीं करेगा। (यह आपको उन प्रगति की संख्या से अधिक प्रगति पट्टी का उपयोग नहीं करने देगा जो आप जाँच रहे हैं या 1 से कम है)


1
आप tput colsटर्मिनल विंडो की चौड़ाई का पता लगाने और तदनुसार प्रगति पट्टी का उपयोग करने के लिए उपयोग कर सकते हैं ।
मिकेल

1

एएनएसआई एस्केप कोड का उपयोग करके यहां एक और दृष्टिकोण दिया गया है:

#!/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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.