「何もしない」コマンドを利用する(シェルスクリプト)

課題

ヌルコマンドという何もしないらしいコマンドの存在理由がわからない。

解決法

ヌルコマンド(:)は、呼び出しても何も実行せず、"たいていは"成功を返すコマンドである(失敗させる実行方法は今回は述べない)。 ヌルコマンドはその特異性により実は用途が色々とある。 この記事ではそのうちのいくつかを紹介する。

コマンドの記述が必要な場所に記述する

例えば if-then-else 文について述べる。 if-then-else 文は以下のような構文である。

if "条件"; then
  "条件" が真のときに実行するべきコマンド ... ①
else
  "条件" が偽のときに実行するべきコマンド ... ②
fi

ここで、実質的に②のみが必要で①の内容が必要ないから①を空にする、ということは推奨できない。 環境によっては空の場合にエラーを発生させてしまうからだ。

以下のようなスクリプトで挙動を確認してみる。 このif-then-elseの条件は真である。 ただし真の場合に実行するべきコマンドはコメントアウトされており、実行コードとしては何も存在しない。

$ cat if_then_else_empty.sh 
#!/bin/bash                                                                                        

if [ $SHELL == '/bin/bash' ]; then
  # echo "this is the true case"                                                                   
else
  echo "this is the false case"
fi

このスクリプトを実行すると当環境(M2 MacのTerminal)では以下のようなエラーとなった。

$ ./if_then_else_empty.sh 
./if_then_else_empty.sh: line 5: syntax error near unexpected token `else'
./if_then_else_empty.sh: line 5: `else'

次にヌルコマンドを記述してみる。

$ cat if_then_else_empty.sh 
#!/bin/bash

if [ $SHELL == '/bin/bash' ]; then
  # echo "this is the true case"
  :
else
  echo "this is the false case"
fi

再度実行すると、エラーが発生しなくなった。

$ ./if_then_else_empty.sh 
$ 

空ファイルを作成する

以下のようにもともと存在しないファイル名にリダイレクトすることで、その名前の空ファイルを作成できる。

$ ls
$ : > emptyfile

中身を確認すると確かに空である。

$ cat emptyfile
$ 

上記は touch コマンドと動作が類似している。

ただし、リダイレクト先として指定したファイルがすでに存在する場合は動作が異なる。 touch コマンドの場合は、タイムスタンプを更新するのみでファイルの中身については変更しない。 一方で、ヌルコマンドのリダイレクト先として指定した場合、既存の中身が削除されて空ファイルになってしまうので、注意すること。

$ cat existfile 
exist!!!
$ : > existfile 
$ cat existfile 
$ 

パラメータ展開の副作用を反映する

例えば ${param=val} の形式のパラメータ展開は、param 変数が未定義の場合、param 変数にval 値を代入する。 これを他に影響なく最小限で実行するためにヌルコマンドを利用できる。

$ unset param
$ : ${param=123}
$ echo $param
123

ここで、ヌルコマンドは必要ないのではと思う人がいるかもしれない。 しかしそれは文法的に問題がある。 実際に実行してみるとエラーが発生するが、エラー内容から、シェルがどのように解釈したのかがわかる。

$ unset param
$ ${param=123}
- bash: 123: command not found

つまりシェルは代入された値(123)をコマンド名として解釈したということだ。 もちろんそのようなコマンド名のコマンドは存在せず、コマンドの実行を失敗したということになる。

所感

個人的には「コマンドの記述が必要な場所に記述する」ために利用することが多い。 もちろん、この記事でそれ以外に説明した用途や、この記事で説明していない用途でも利用できるかもしれない。 しかしヌルコマンドを(半ば無理やり)利用することで、その記述の意図が伝わりづらくなる可能性もある。 スクリプトの読み手にスクリプトの意図をスムーズに届けることを優先したいなら、ヌルコマンドを利用しない方法も一度は検討するべきだ。