答え: 最初から
(この記事は地平線に行くとのマルチポストです)
最初の touch コマンド
FreeBSD の touch のマニュアル曰く、touch コマンドは Version 7 の AT&T UNIX で登場したそうです。
HISTORY
A touch utility appeared in Version 7 AT&T UNIX.
touch(1) - FreeBSD Manual Pages
このときの man を読むと、すでに「ファイルが存在しなければ作成する」ということが記載されています。
DESCRIPTION
Touch attempts to set the modified date of each file.
This is done by reading a character from the file and writing it back.
If a file does not exist, an attempt will be made to create it unless the -c option is specified.Touchは、それぞれのファイルの修正日時の設定を試みます。
これは、ファイルから文字を読み取り、それを書き戻すことによって行われます。
ファイルが存在しない場合、-c オプションが指定されていない限り、ファイルの作成を試みます。unix-history-repo/touch.1 at Research-V7 · dspinellis/unix-history-repo · GitHub
ソースコード1を読むと、たまたまファイルがなければ作るようになったのではなく、あえてそのように実装していたことが分かりました。
具体的には、まず stat(3)
でファイルの存在を確認して、なければ create(3)
でファイルを作るという実装をしていました。
unix-history-repo/touch.c at Research-V7 · dspinellis/unix-history-repo · GitHub
# include <sys/types.h>
# include <sys/stat.h>
touch(force, name)
int force;
char *name;
{
struct stat stbuff;
char junk[1];
int fd;
if( stat(name,&stbuff) < 0)
if(force)
goto create;
else
{
fprintf(stderr, "touch: file %s does not exist.\n", name);
return;
}
if(stbuff.st_size == 0)
goto create;
if( (fd = open(name, 2)) < 0)
goto bad;
if( read(fd, junk, 1) < 1)
{
close(fd);
goto bad;
}
lseek(fd, 0L, 0);
if( write(fd, junk, 1) < 1 )
{
close(fd);
goto bad;
}
close(fd);
return;
bad:
fprintf(stderr, "Cannot touch %s\n", name);
return;
create:
if( (fd = creat(name, 0666)) < 0)
goto bad;
close(fd);
}
では、なぜファイルが存在しない場合にエラーにするのではなく、ファイルを作るようにしたのでしょうか。
それは、わかりませんでした(ぇ
まとめ
いかがでしたでしょうかw
ソースコードにコメントはなく、なぜこのような仕様にしたのかはこのコードを書いたDennis M. Ritchie氏2しか知る由がなさそうです。ただ、2011年に亡くなられたので、もはや聞くことはできません…。
おそらく、その方が便利だからだとは思うのですが、確証がありません。
もしかしたら本か何かに、その意図が残されているかもしれません。
ご存じの方がいましたら、情報をお寄せいただければと思います。