test と [
昨日のエントリに関して。
きむら 『test ([)内部で、自分が ’[’ という名前で呼ばれたら引数で渡された ’]’ を
特別扱い(というのか?)してるんですよね。』 (2006/12/31 01:11)
そうそう、確かそうだったはず、と思うものの、念のために GNU coreutils 5.93 のコードを確認。あれ、[ は test の hard link じゃない。
test は test.c から、[ は lbracket.c からコンパイルされるようになっているんだけど、test.c の中身を抜粋するとこんな感じ。
#ifndef LBRACKET # define LBRACKET 0 #endif /* The official name of this program (e.g., no `g' prefix). */ #if LBRACKET # define PROGRAM_NAME "[" #else # define PROGRAM_NAME "test" #endif
if (LBRACKET) { /* Recognize --help or --version, but only when invoked in the "[" form, and when the last argument is not "]". POSIX allows "[ --help" and "[ --version" to have the usual GNU behavior, but it requires "test --help" and "test --version" to exit silently with status 1. */ if (margc < 2 || !STREQ (margv[margc - 1], "]")) { parse_long_options (margc, margv, PROGRAM_NAME, GNU_PACKAGE, VERSION, usage, AUTHORS, (char const *) NULL); test_syntax_error (_("missing `]'\n"), NULL); } --margc; }
で、lbracket.c は2行。
#define LBRACKET 1 #include "test.c"
[ で呼ばれたときは ] を特別扱いしているのには違いないんだけど、argv[0] を見て動的に挙動を切り替えるんじゃなくて、コンパイル時に挙動が決まっているというオチ。
まぁ、これも GNU coreutils を採用している OS での話で、FreeBSD なんかは昨日書いたように test と [ は hard link で argv[0] を見て動的に挙動を切り替えているというので正しい。
あと、コメントにも書いたけど、bash/zsh では test は builtin だから実際にこれらのプロセスが生成される機会は結構少ない。Linux だと大抵の場合 /bin/sh は /bin/bash への symbolic link だし。