【プログレスバー】ターミナルを楽しく使う!ターミナル上で動くプログレスバーの作り方

シェルスクリプト

プログラミングを学習の皆さん、ターミナルをよく使いますよね?

プログラミング学習を始めたての頃は、「なんかターミナルって難しそう」、「ターミナルって英語表示だから使うのに抵抗がある」
なんて思ったことないですか?ちなみに僕はターミナルに抵抗がありました。

そんな気持ちを持っている方のために、ターミナルを使うのが楽しくなるプログラムを紹介したいと思います。

今回は、シェルスクリプトと呼ばれる言語を使って、プログレスバーを作っていきます!

シェルスクリプトって初めて聞いたよ、知らないよって人も安心してください。わかりやすく説明してあるので、気楽に読み進めていってください。

シェルスクリプトとは?

今回、シェルスクリプトという言語を使ってプログレスバーを作成していきます。

シェルスクリプトとは、シェルに実行してほしいことを伝えるプログラムです。シェルスクリプトを使用することで、複数のコマンドを実行することができ、作業の効率化が見込めます。

シェルは、ターミナルの裏側で動いているコンピュータと人間を繋ぐ役割をしてくれる方だと思ってください。人間側が「コンピュータよhitori.txtというファイルを作成せよ!」って言えば、コンピュータが日本語をそのまま理解して動いてくれる、、、なんてことはないですよね。

シェルは人間の言葉をコンピュータが理解できるように翻訳してくれます(厳密には違うが)。

シェルスクリプトはこのシェルに人間側がしたいことをまとめたファイルのことです。

プログレスバーを作ってみよう!

早速、プログレスバーを作っていこうと思います!

完成すると以下のようになります。

では作っていきましょう!

以下が今回作成するプログラムです。これをコピーして、 拡張子が.shのファイルにペーストすればzsh ファイル名で利用できます。

#!/usr/bin/env bash

if [[ $# -eq 0 ]];then
	timer=500
elif [[ $# -eq 1 ]];then
	timer=$1
else
	echo "Usage: ./progress_bar.sh [time]"
	exit 1
fi

echo "約$((${timer}/100))秒間かかります。終了したいときはCtrl+c"

trap 'echo -n -e "\033[?25h"; exit $STATUS' SIGINT

echo -n $'\033[?25l';
for i in $(seq $timer); do
	sleep 0.01;
	if [[ $(($i%10)) -ne 0 ]]; then
		echo -n $'\b';
	fi
	echo -n -e "\U$(printf "%X" 0x258B )";
done
echo $'\033[?25h';

では、このコードについて解説していきます。

まず一行目の#!/usr/bin/env bashシバン呼ばれる記述です。PythonやRubyを学習したことある方はコメント?と思うかもしれませんが、コメントとは少し違います。コメントは実行するときは影響のないものですが、シバンは影響を及ぼす場合があります。

シバンとはLinuxなどのUNIX系OSでインタプリタを指定するために必要な記述です。インタプリタは人間の書いた高級言語を逐次機械語に翻訳して実行することです。

UNIX系OSで必要な記述なのでWindowsの方は必要ありません。筆者はMacを使用しているので必要です。

if [[ $# -eq 0 ]];then
	timer=500
elif [[ $# -eq 1 ]];then
	timer=$1
else
	echo "Usage: ./progress_bar.sh [time]"
	exit 1
fi

上記のコードは使い方に関する記述です。今回は2つの利用パターンにしてあります。

  • コマンドライン引数になにも入力されなかった時、5秒間のプログレスバーにする
  • コマンドライン引数に時間を指定した場合、その時間のプログレスバーにする

コマンドライン引数とは実行時に指定した引数のことです。例えば、./sample.sh 2とコマンドラインで実行した時は、2がコマンドライン引数となります。複数指定することが可能で、./sample 2 many hitoriと実行したときは、2manyhitoriの3つがコマンドライン引数になります。

今回は引数がない場合、1つある場合、2つ以上の場合で処理を分けます。

シェルスクリプトでのif文は

if [[ ]]; then
    #コードを記入
elif [[ ]]; then
    #[[ ]]の中の単語は左右に空白を入れること
else
    #最後にfiを書くこと
fi

このようになります。少し独特ですが、if, else, elifと見慣れたところもあります。

if [[ $# -eq 0 ]];then、これはコマンドライン引数が0個だったら、という処理を行います。[[ ]]は他の言語でいうところのカッコ()に当たります。

$#はコマンドライン引数の個数を、-eqはequalということで等しい==を表します。よって、if [[ $# -eq 0 ]];thenは「もしコマンドライン引数の個数($#)が0に等し(-eq)かったら」ということになります。

そして次の行ではtimerという変数に500を代入しています。timerに代入された値はtimer/100秒間のプログレスバーを作るという意味です。ここでは500を代入しているため、5秒間のプログレスバーになります。

ここで気をつけなければいけないのが=の左右です。よくプログラムを書くとき、=の左右に半角スペースを入れる人がいますが、シェルスクリプトでそれをやるとエラーになります。絶対に=の左右に半角スペースを入れないようにしてください

else文で実行されるecho "Usage: ./progress_bar.sh [time]"exit 1は今回の仕様に合わないときは使い方を出力して、終了ステータスを1にして終了するということです。

echo "出力したい文章"でターミナル上に文章を出力できます。

trap 'echo -n -e "\033[?25h"; exit $STATUS' SIGINT

これはCtrl+cで終了させたときの処理を書いています。”\033[?25h”は以降に説明します。

echo -n $'\033[?25l';
for i in $(seq $timer); do
	sleep 0.01;
	if [[ $(($i%10)) -ne 0 ]]; then
		echo -n $'\b';
	fi
	echo -n -e "\U$(printf "%X" 0x258B )";
done
echo $'\033[?25h';

これがこのスクリプトのメインです!

最初のecho -n $'\033[?25l';はターミナル上のカーソルを非表示にします。\033[?25lはエスケープシーケンスと呼ばれる特殊な文字列です。これでカーソルが非表示になります。

カーソルを非表示にすることでプログレスバーっぽくなります。ここ重要!

プログラムが終了したらカーソルは再度表示させたいため、最後の行echo $'\033[?25h';で一通り処理が終わったらカーソルを表示させます。

for i in $(seq $timer); do
	sleep 0.01;
	if [[ $(($i%10)) -ne 0 ]]; then
		echo -n $'\b';
	fi
	echo -n -e "\U$(printf "%X" 0x258B )";
done

for文はPythonやRubyに似ています。最後にdoneを書くことを忘れないようにしましょう。

seqはコマンドです。seq 整数とすることで1から指定した整数までの連続した整数を返します。

$(コマンド)はカッコの中のコマンドを実行して得られた結果を使用するということです。

つまりtimer変数に500が代入されていたとして、$(seq $timer)は1,2,3,…,498,499,500ということになります。

したがって、for i in $(seq $timer)はこの連続する整数を一つずつ変数iに入れてfor文の中身を実行します、ということになります。

そして、for文の中身について

sleep 秒数でその時間分、実行が止まります。今回はsleep 0.01ですから、0.01秒間プログラムを止めています。プログラムをsleepコマンドで止めないと一瞬で出力されてプログレスバーになりません。プログレスバーにするために、プログラムを止めてそれっぽくしましょう。

その後、塗りつぶされた長方形を出力しています。こんなやつ∎(文字化けしないでお願い)

これで完成です!!10秒間のプログレスバーを実行したいときはzsh ./ファイル名 1000としましょう。

コマンドライン引数が1つであるため、timerに1000が代入され、(1000 / 100)秒間のプログレスバーが実行されます。ただし、これは厳密に10秒間というわけではないです。正確さにかけるので、あくまでお遊びということで。

おわりに

今回はシェルスクリプトを使ってプログレスバーを制作してみました。

シンプルですが地味に面白いですよね〜。∎(塗りつぶされた長方形)を#にすると違ったバーを楽しめます。

また、出力する際の色を変更してみても面白いです(面倒でやりませんでした)。

お疲れ様でした〜それではまた違う記事で会いましょう!

コメント

タイトルとURLをコピーしました