bashで進行状況バーを作成する


13

bashでプログレスバーを作成するにはどうすればよいですか?

これは私のスクリプトです:

 #!/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 Ubuntuや他の多くのディストリビューションにプリインストールされており、全画面(ただし端末ベース)の進行要素が表示されます。

dialogはのスーパーセットでwhiptailあるため、この例は両方で同等に機能します。より高度なUI要素を提供するため、ファイルピッカーやフォームなどのユーザーインタラクションを探している場合に便利かもしれませんが、多くのシステムにプリインストールされていないという欠点があります。

ホイップテール

ダイアログ

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

スクリプト出力はパーセンテージとして解釈されるため、それに応じて出力を調整する必要がある場合があります。

Whiptail and Dialogでは、かなりわかりにくい構文を使用して、実行時にテキストを変更することもできます。

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またはのスタイルで1行のプログレスバーを表示するコマンドは知りませんが、wget他の人がここで共有しているように、その機能を追加する単純なBash / Perl / sedスクリプトがたくさんあります。


ループのプロセスを表示するにpvは、ループの出力を検索するか、偽の出力を作成します(たとえば、echoすべての反復で)、パイプしpvて、で反復カウントを指定し-sます。不要な場合は、ループの標準出力をにリダイレクトすることを忘れないでください/dev/nullこのアプローチを示す例を次に示します。
デザート

6

を使用zenityして、単純なGTKダイアログウィンドウを作成できます。使用可能なオプションの1つは、進行状況バーのダイアログです。

このようなウィンドウを作成するには、を使用し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

次の2つのモードがあります。

  • 脈動:進行状況バーは脈動しており、何かが実行されていることを示していますが、進行状況については何も伝えません。これを行うには、--pulsatingオプションを設定します。

  • manual:現在の進捗率をzenityコマンドの標準入力にパイプして、進捗バーを更新する必要があります。
    この例は、次のようになります。前のコマンドはサブシェルにグループ化されているためzenity、最後のコマンドの出力だけでなく、すべての出力がダイアログにリダイレクトされることに注意してください。

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

念のため、これもオプションになります。
バイトコマンダー

1
申し訳ありませんが、これはGUIプログレスバーウィンドウです。ターミナルでプログレスバーを作成します。たとえば、スクリプトのチェック中に表示したい==>[ ###########--------------] 52%
Black Hawk

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

ANSIエスケープコードを使用した別のアプローチを次に示します。

#!/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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.