「とにかく楽をして運用しよう」と考えていくと、いろいろな処理をシェルスクリプトで自動化したいと思うようになる。シェルスクリプトは現物を読みながら学んでいくとわかりやすいのだが、シェルスクリプトを読んでいると時折「true」や「false」というコマンドが出てくることに気がつくと思う。両方とも本当にちょっとした機能しか持っていないコマンドなのだが、知っていると便利なことも多いので、ここで取り上げておこう。

何も起こらないコマンド!?

まず、次のようにtrueコマンドとfalseコマンドを実行してみてほしい。

●trueコマンドの実行例

% true
%

●falseコマンドの実行例

% false
%

上記のようにtrueコマンドを実行してもfalseコマンドを実行しても何も表示されないし、実際何も起こらない。ではいったい何をするコマンドなんだということになるが、true/falseコマンドは、それぞれ終了時の返り値が「0」「1」で終わるコマンドである。

Bourne Shell系のインタラクティブシェルを使っているのであれば(macOSとほとんどのLinuxディストリビューションはシェルを変えていないかぎり、これだ)、次のように「$?」の値を表示させると直前に実行したコマンドの終了値を調べることができる。

●trueコマンドの終了値は0

% true
% echo $?
0
%

●falseコマンドの終了値は1

% false
% echo $?
1
%

これは、ソースコードを見てみると一目瞭然だ。次のソースコードはFreeBSDのtrueコマンドとfalseコマンドのソースコードを抜粋したものだが、返り値に「0」ないし「1」を返すことしか行っていないことがわかる。

●trueコマンドのソースコード

int
main(void)
{
        return 0;
}

●falseコマンドのソースコード

int
main(void)
{
        return 1;
}

UNIX系OSのシェルでは、0で終了したコマンドは正常終了、それ以外の値で終了したコマンドは正常終了ではない、と扱うのが慣例になっている。つまり、trueコマンドは必ず正常終了するコマンドであり、falseはかならず正常終了しないコマンド、ということになる。

「だからどうした」と思われるかもしれないが、必ず正常終了するコマンドや、絶対に正常終了しないコマンドというのは、それはそれで使い道がある。例えば(シェルスクリプトの書き方はここでは特に説明しないが)ずっと処理がループしてほしい場合などには、次のように条件のところにtrueコマンドを書いておけば、終了することなく永遠に処理が繰り返されるようになる。

●whileの条件式にtrueコマンドを指定して処理が永遠にループするようにしたスクリプト

#!/bin/sh

while true
do
        echo -n /
done

実行すると永遠にスラッシュが出力される

これを利用すると、次のようにユーザーから入力を求め、条件に合う値が入力されるまで処理を繰り返すといったことができる。

#!/bin/sh

while true
do
        echo -n "continue? [Y/n] = "
        read ans
        if [ "n" = "$ans" ]
        then
                break
        fi
done

実行すると想定された値が入力されるまでループする

また、trueコマンドやfalseコマンドはシェルスクリプトの終了値を指定する場合にも使ったりする。例えば、grepコマンドは検索に一致した場合には「0」で終了するが、一致しなかった場合には「1」で終了する。次のような感じだ。

$ grep FreeBSD /COPYRIGHT > /dev/null
$ echo $?
0
$ grep FreeeBSD /COPYRIGHT > /dev/null
$ echo $?
1
$

こうした終了値は、都合が悪いことがある。検索に一致しなくても「0」で正常終了してほしいケースがあるのだ。そうした場合には次のようにシェルスクリプトでgrepコマンドを実行し、スクリプトの最後にtrueコマンドを書いておけばよい。シェルスクリプトは最後に実行したコマンドの終了値をシェルスクリプトの終了値として扱うため、次のように書いておけば常に正常終了することになる。

#!/bin/sh

grep $@
true

実行すると、次のように検索が一致しなかった場合でも正常終了することを確認できる。

% ./grep2.sh FreeBSD /COPYRIGHT > /dev/null
% echo $?
0
% ./grep2.sh FreeeBSD /COPYRIGHT > /dev/null
% echo $?
0
%

逆に、ある条件になった場合には正常終了させたくないといった場合にfalseコマンドを使うこともある。……とは言ってみたものの、falseコマンドを明示的に使うことはあまりないように思う。基本的には、trueコマンドの使い方を把握しておけばよいだろう。

Makefileを書くようになったりすると、先ほどのgrepコマンドのように特定の動作で0以外の値で終了し、処理が止まってしまうといった事態に遭遇することがある。そうした場合も、trueコマンドを使って回避することができる。

今は具体的な使い方が思い浮かばなくても、シェルスクリプトを書いたり、Makefileを書いたりするようになるといずれお世話になるコマンドとなるはずだ。その日のために、ぜひ覚えておいていただきたい。