Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

UNIXコマンド「test」が思ったより使える件

一般に、「test」はファイルが存在するか確認する際に使われるコマンドです。
結果は標準出力ではなくコマンドの終了状態に格納されるため、注意が必要です。

$ test -e aasm_sample.rb ; echo $?

とまぁ、これ単体だとイマイチありがたみがわかりませんが
設定されている書式を使うと色々便利な事ができます。

より新しい、より古い

より新しいファイルを検索したい場合、以下のように「対象ファイル -nt 比較ファイル」の順で呼び出します。

$ test aasm_sample.rb -nt sample1.rb ; echo $?
0

逆に、古いか判断したい場合は「対象ファイル -ot 比較ファイル」の順です。

$ test aasm_sample.rb -ot sample1.rb ; echo $?
1

空か内容があるか

$ touch hoge.log

と空ファイルをつくったとします。ファイル自体は存在しますが、何もありません。
この場合、空ファイルか確認するのは -nオプションです。

$ test -n hoge.log ; echo $?
0

一方、何か入っているか確認する場合は-zオプションを使います

$ test -z hoge.log ; echo $?
1

エイリアス?について

UNIXの部屋 コマンド検索:test (*BSD/Linux)を見ると

この [ というのは実はコマンドで、またの名を test という

とあり、シェルのif文で使われていたアレが、実はtestのエイリアスだった事がわかります。
ためしに、冒頭のコマンドを再現すると…

$ [ -e aasm_sample.rb ; echo $?
bash: [: missing `]'
2

とエラーがでますが

[ -e aasm_sample.rb ] ; echo $?
0

とちゃんと閉じると結果を出します。
コマンドでも、末尾を見るやつがあるんですね…
ためしに、シンプルなままで美しいと評判のPlan9のtestコマンドソースをみても

/*
 * POSIX standard
 *	test expression
 *	[ expression ]
 *
 * Plan 9 additions:
 *	-A file exists and is append-only
 *	-L file exists and is exclusive-use
 *	-T file exists and is temporary
 */
/* 中略 */
void
main(int argc, char *argv[])
{
	int r;
	char *c;

	ac = argc; av = argv; ap = 1;
	if(EQ(argv[0],"[")) {
		if(!EQ(argv[--ac],"]"))
			synbad("] missing","");
	}
	argv[ac] = 0;
	if (ac<=1)
		exits("usage");
	r = e();
	/*
	 * nice idea but short-circuit -o and -a operators may have
	 * not consumed their right-hand sides.
	 */
	if(0 && (c = nxtarg(1)) != nil)
		synbad("unexpected operator/operand: ", c);
	exits(r?0:"false");
}

/* 後略 */

と、閉じる記法はそのまま残っている事がわかります。
また一つ勉強になりました。