次に以下の部分を解説します。 この部分は、今回のプログラムの中心的な処理になります。
echo -n "backup ${target_file_name} to ${backup_file_name} ? [yes/no] : "
while read confirmation; do
case $confirmation in
'yes' ) tar zcf ${backup_file_name} ${target_file_name}
break ;;
'no' ) echo "stopped operation"
exit 0 ;;
*) echo "unknown option. try again."
echo -n "backup ${target_file_name} to ${backup_file_name} ? [yes/no] : " ;;
esac
done
この部分を理解するためにまず、キーボードから入力を待つ方法、ループ、そして条件分岐の一つであるcaseの構文を理解する必要があります。 まずこの三つを解説します。
シェルスクリプトではキーボードからの入力を受け取って動作を制御したりすることが可能です。キーボードからの入力待ちをおこなうにはreadコマンドを使用します。 シェルのプロンプトからreadコマンドに引数として変数名を与えると、入力を待ち状態に入ります。この入力待ち状態は、Enterキーがたたかれるまで継続します。 Enterキーが叩かれたら、それまでにキーボードから入力された文字列が引数で変数名を与えた変数に格納されます。
read 変数名
以下のスクリプトをsay_something.shとして作成します。
#!/bin/bash
echo -n "say something : "
read message
echo "message : $message"
これを実行してみます。 最初のechoコマンドで"say something : "という出力をして入力待ちに入りますので、何か入力した後に、Enterキーで終了させます。
$ ./say_something.sh
say something : hello(Enter)
message : hello
となると思います。
ちなみにecho に-nオプションをつけたのは、行末の改行を出力抑制するためです。 readを使用したプロンプト表示でよく使うので覚えておくと便利です。
シェルスクリプトでは一定の条件の間、同じ処理を繰り返すということがしたい場合があります。そのような条件判定で繰り返し制御をおこなうループはwhile構文で実現します。 whileの基本的な構文は以下の通りです。
while 条件式
do
実行文
done
条件式の内容が真(0)である限り、実行文が繰り返され、条件式の内容が偽(0以外)になるとループが停止します。
他のプログラミング言語同様、if文以外の条件分岐としてcase文も使えます。多数の条件分岐を行うときなどではcaseのほうが記述量が少なく便利だったりする場合があります。 caseを用いた条件分岐の基本的な構文は以下の通りです。
case $var in
'yes' ) 実行文1 ;;
'no' ) 実行文2 ;;
*) 実行文3 ;;
esac
この場合、$varの値が'yes'だった場合は実行文1、'no'だった場合は実行文2、それ以外の場合は実行文3が実行されることになります。 caseを用いた条件分岐ではif文のように値の範囲を条件に分岐したりすることはできません。このあたりは使い分ける必要があります。
ここまでの情報でソースコードを見ていきます。 最初の部分はユーザに確認の文章を表示するところです。
echo -n "backup ${target_file_name} to ${backup_file_name} ? [yes/no] : "
これから${backup_file_name}を${target_file_name}に保存するので最終確認になります。 ユーザからのキーボードでの入力としては、yesまたはnoを期待しています。
ここからwhileのループに入りますが、なぜか、条件文のところにread confirmationがあります。
readコマンドを実行して、キーボードからの入力があり、最後にEnterが入力され、正常にreadコマンドが終了すると、readコマンドが真を返します。 ということは、正常に入力があると、whileの条件文がtrueになり、ループの中の処理が実行されることになります。 whileの条件文はいつも真を返すので無限ループになるように作られています。無限ループについては別の場所で止める必要があります。
while read confirmation; do
case $confirmation in
'yes' ) tar zcf ${backup_file_name} ${target_file_name}
break ;;
'no' ) echo "stopped operation"
exit 0 ;;
*) echo "unknown option. try again."
echo -n "backup ${target_file_name} to ${backup_file_name} ? [yes/no] : " ;;
esac
done
キーボードからの入力が完了するとwhileループの中の以下のcase文が実行されます。 case文では、readで作成した$confirmationの値を使って条件分岐をしています。 $confirmationの値が'yes'の時はtarを使った圧縮処理を実行します。また、$confirmationの値が'no'だったときは処理を停止します。$confirmationの値が'yes'でも'no'でもなかったときは、入力の誤りとみなし再度、確認を繰り返します。これが無限ループになっていた理由です。
case $confirmation in
'yes' ) tar zcf ${backup_file_name} ${target_file_name}
break ;;
'no' ) echo "stopped operation"
exit 0 ;;
*) echo "unknown option. try again."
echo -n "backup ${target_file_name} to ${backup_file_name} ? [yes/no] : " ;;
esac
なお、case文の分岐では$confirmationの値が'yes'の場合は'break'が最後に実行されています。 breakはループを抜け出すときに利用します。この場合、$confirmationが'yes'になった時点で目的の処理が実行されます。その後、プログラムを終了させるためにループを抜け出しています。