はじめに
Unix コマンドのコマンド名は動詞とは限りませんし、Unix コマンドの引数の文法は英語の文法を踏まえて作られているわけではありません。Unix コマンドの文法は実用目的で設計されています。間違った前提で物事を考えると間違った答えがでてしまいます。現実と矛盾していることが間違っているという証拠です。
COBOL という言語で人類は思い知ったはずです。英語の文法をそのまま採用すると使いづらくなるということを。DSL のように英語の文法を参考にするとわかりやすいというメリットはありますが、DSL が完全に英文ではないように最終的にはプログラムに適した別の文法のほうが実用的なのです。
この記事は「ド素人に「ターミナル」の必要性を熱弁する60分【黒画面に白文字のアレ】#137」という動画で、コマンドが動詞とか名詞とか目的語とかいう話がでてたのをきっかけに、思いつたので書きました。動画はちゃんと見ていませんし、この記事はこの動画へのコメントではありません。この記事を書くことのきっかけとなった動画としての紹介です
動詞とか目的語とか考えるな!
正直、Unix コマンドの文法が動詞とか目的語とか考えるのはナンセンスです。なぜなら、実際のコマンドは昔からめちゃくちゃだからです。
Unix コマンドは動詞でないもののほうが(多分)多い
UNIX コマンドは動詞ではありません。これは、少し調べて考えればわかることです。以下は、Version 7 Unix にあるコマンド一覧です。この中に一体いくつ動詞があるでしょうか?
ac col f77 m4 prof spell tr
adb comm factor mail ps spline troff
ar cp file make pstat split true
arcv crypt find man ptx strip tsort
as cu graph mesg pubindex struct tty
at date grep mkconf pwd stty uniq
awk dc icheck mkdir quot su units
bas dcheck intro mkfs ranlib sum uucp
basename dd iostat mknod ratfor sync uux
bc deroff join mount refer tabs wait
cal df kill mv restor tail wall
calendar diff ld ncheck rev tar wc
cat diff3 lex newgrp rm tbl who
cb du lint nice roff tc write
cc dump ln nm sa tee xsend
cd dumpdir login od sed test yacc
chmod echo look passwd sh time
chown ed lookall plot size tk
clri eqn lorder pr sleep touch
cmp expr ls prep sort tp
よく使うコマンドにも、動詞でないものはいっぱいあります。awk
、cd
、chmod
、grep
、mkdir
、rmdir
、ps
、sed
、sh
、true
、false
、uniq
、wc
などです。
awk
は3人の開発者の名前(Alfred Aho、Peter Weinberger、Brian Kernighan)の頭文字です。cd
は change (動詞)directory(名詞)の頭文字です。sh
はシェルですし、uniq
は unique を意味する形容詞です。
コマンドの使い方が英語の文法に近ければ(英語圏の人には)使いやすいのは事実ですが、UNIX コマンドの「コマンド名」は名前でありどちらかといえば名詞です。
grep は元々動詞ではない
grep
は現在動詞となっていますが、元々は ed
(テキストエディタ: 名詞)で入力するコマンド g/re/p
(global / regular expression / print) の略です。
コマンド名を動詞にするとUnix哲学を実践できなくなる
例えばファイルを作成するコマンドとして create
コマンドを作ったとしましょう。
それでは、動画ファイルを作成するコマンドは? 画像ファイルを作成するコマンドは? HTML ファイルを作成するコマンドは? Excel ファイルを作成するコマンドは? 何にしたら良いでしょうか?
create
コマンドがさまざまな形式に対応するのでは Unix 哲学の「一つのことをうまくやる」を満たしていません。create_excel
コマンドだともはや動詞ではありませんね。
昔からある Unix コマンドは「初期の Unix 時代ではファイルぐらいしか扱うものがなかった」から、動詞だけですんだのです。そして Unix が成長するとともに、コマンド名を動詞にするのでは都合が悪く現実的ではなくなりました。awk
や sed
など新しく作られたコマンドほど、コマンド名は動詞ではなくなっています。
コマンド(命令)は動詞ではなく文章
コマンドは日本語にすれば命令ですが、「作れ!」だけでは何を作っていいのかわかりません。「命令」とは「単語(動詞)」ではなく「文章」です。ちなみに POSIX の用語では、コマンドとはパイプラインや複合コマンドなど、長い文章を指す言葉です。一つのコマンドはシンプルコマンドと言われます。
A command is one of the following:
- Simple command (see 2.9.1 Simple Commands )
- Pipeline (see 2.9.2 Pipelines )
- List compound-list (see 2.9.3 Lists )
- Compound command (see 2.9.4 Compound Commands )
- Function definition (see 2.9.5 Function Definition Command )
Unix コマンドの引数の設計
実際の Unix コマンドがどのような引数の設計になっているかを見ていきましょう。
昔(?)は From To の順番が多かった
Unix コマンドの引数は、From To の順番であることが多いです。元からそうですし、現在でもそのようなコマンドがあります。すぐに思いつくのが cp
や mv
でしょう。
cp [OPTION]... SOURCE... DIRECTORY
現在とは違いますが、sort
コマンドも昔は sort 入力ファイル 出力ファイル
の順番でした。
sort input output
From To はパイプと相性が悪い
パイプが発明され、sort
コマンドのようなフィルタとなるコマンドでは From To の書式は相性が悪いことが判明しました。現在の sort
コマンドは複数のファイル名を受け付け、複数のファイル名を並び替えることができ、出力先を省略した時に出力を標準出力に出力します。
sort file1.txt file2.txt
しかし、以前の sort
コマンドの文法 sort input output
では 2 番目のファイルは出力ファイルなので都合が悪いことになります。Version 7 Unix の sort では、実用目的のために 出力先は -o
オプションで指定するように変更されました。
sort -o out.txt file1.txt file2.txt
cp
や mv
と言ったパイプを使わないコマンド、つまりフィルタコマンドでないものは、標準出力に出力しない = 出力先を必ず指定する必要があるので、そのままの文法で残りました。
From To は xargs と相性が悪い
xargs
コマンドは引数が多すぎる時に、Unix のコマンドライン引数の制限を乗り越えるために作られました。
find . -name "*.txt" | xargs touch
xargs
コマンドがうまく機能するには、コマンドライン引数の最後に複数のファイル名を指定できる 必要があります。上記は、以下のように変形されて実行するからです。
touch file1.txt file2.txt file3.txt ...
この xargs
コマンドの仕様は cp
と相性が悪いです。なぜなら、cp
コマンドは To(出力先)を最後に指定しなければならないからです。
cp [OPTION]... SOURCE... DIRECTORY
つまり From To の書き方は xargs と組み合わせた時に破綻してる のです。GNU コマンドではこの問題に対処するために次のような構文を受け付けるようになっています。
cp [OPTION]... -t DIRECTORY SOURCE...
パイプとはなにか?
パイプ記号「|」は into の別名に過ぎない
パイプの記号は、パイプの導入の過程で「who into cat into grep
と口で言うのは簡単だが、これをそのままコマンドとして簡潔に書くにはどうすれば良いのだろうか?」という試行錯誤から発明されています。その詳細は以下で語られています。
つまり、パイプ記号は into という単語の別名であり、あえていうなら前置詞です。
コマンド同士をつなぐ「庭のホース」
パイプの考案者である Douglas McIlroy はパイプの概念を、コマンド同士をつなぐ「庭のホースのようなもの」と考えていました。
コマンドライン引数の良い設計
コマンドライン引数の良い設計とは、他のコマンドと組み合わせやすい設計です。具体的には固定数の引数の後に(必要なら)可変長の引数(複数の引数)を渡せるようにすること です。GNU コマンドなどは、オプションを引数の最後に書くことができますが、手段の一つとして用意されているだけなので問題ありません。
コマンド名 [オプション] [固定数の引数] [可変長引数]...
コマンド名 [グローバルオプション] サブコマンド [オプション] [可変長引数]...
コマンド名は動詞にできるのなら別にしても構いませんが、動詞にする必要はありません。実際に Unix コマンドには動詞でないものはいくつもあります。何かを実行するサブコマンドは動詞であることがよくありますが、サブサブコマンドがある場合のサブコマンドはおそらく名詞でしょう。
さいごに
Unix コマンドの仕様が英語の文法を踏まえているかどうかなんて考えなくてよいです。少し考えば明らかな矛盾がいくつも見つかる話に対して、つじつまを合わせようとすることに意味はありません。これは最終的に「Unix コマンドの文法は英語の文法を踏まえていないねという結論で終わる話」です。昔にまだ Unix が小さかった頃は英語風の文法を採用していたけれど、多くのコマンドが作られ複数のファイルを指定するようになり、英語風の文法は破綻したので実用目的のために変化しています。