UNIXのコマンド名は動詞ではないし、英語の文法も踏まえていない

## はじめに

Unix コマンドのコマンド名は動詞とは限りませんし、Unix コマンドの引数の文法は英語の文法を踏まえて作られているわけではありません。Unix コマンドの文法は**実用目的で設計**されています。間違った前提で物事を考えると間違った答えがでてしまいます。現実と矛盾していることが間違っているという証拠です。

COBOL という言語で人類は思い知ったはずです。英語の文法をそのまま採用すると使いづらくなるということを。DSL のように英語の文法を参考にするとわかりやすいというメリットはありますが、DSL が完全に英文ではないように最終的にはプログラムに適した別の文法のほうが実用的なのです。

この記事は「[ド素人に「ターミナル」の必要性を熱弁する60分【黒画面に白文字のアレ】#137](https://www.youtube.com/watch?v=kARg6OYDfgM)」という動画で、コマンドが動詞とか名詞とか目的語とかいう話がでてたのをきっかけに、思いつたので書きました。動画はちゃんと見ていませんし、この記事はこの動画へのコメントではありません。この記事を書くことのきっかけとなった動画としての紹介です

## 動詞とか目的語とか考えるな！

正直、Unix コマンドの文法が動詞とか目的語とか考えるのはナンセンスです。なぜなら、実際のコマンドは昔からめちゃくちゃだからです。

### Unix コマンドは動詞でないもののほうが（多分）多い

**UNIX コマンドは動詞ではありません**。これは、少し調べて考えればわかることです。以下は、[Version 7 Unix にあるコマンド一覧](https://man.cat-v.org/unix_7th/1/)です。この中に一体いくつ動詞があるでしょうか？

```
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 の用語では、コマンドとはパイプラインや複合コマンドなど、長い文章を指す言葉です。一つのコマンドはシンプルコマンドと言われます。

https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_09

> 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 入力ファイル 出力ファイル` の順番でした。

http://squoze.net/UNIX/v2man/man1/sort

```sh:昔の sort は 2 番目のファイルは出力先
sort input output
```

### From To はパイプと相性が悪い

パイプが発明され、`sort` コマンドのようなフィルタとなるコマンドでは From To の書式は相性が悪いことが判明しました。現在の `sort` コマンドは複数のファイル名を受け付け、複数のファイル名を並び替えることができ、**出力先を省略した時**に出力を標準出力に出力します。

```sh:現在の sort は 2 番目のファイルは入力元
sort file1.txt file2.txt
```

しかし、以前の `sort` コマンドの文法 `sort input output` では 2 番目のファイルは出力ファイルなので都合が悪いことになります。[Version 7 Unix の sort](https://man.cat-v.org/unix_7th/1/sort) では、**実用目的のために** 出力先は `-o` オプションで指定するように変更されました。

```sh:現在の sort では出力先はオプションで指定する
sort -o out.txt file1.txt file2.txt
```

`cp` や `mv` と言ったパイプを使わないコマンド、つまりフィルタコマンドでないものは、標準出力に出力しない = 出力先を必ず指定する必要があるので、そのままの文法で残りました。

### From To は xargs と相性が悪い

`xargs` コマンドは引数が多すぎる時に、Unix のコマンドライン引数の制限を乗り越えるために作られました。

```sh
find . -name "*.txt" | xargs touch
```

`xargs` コマンドがうまく機能するには、**コマンドライン引数の最後に複数のファイル名を指定できる** 必要があります。上記は、以下のように変形されて実行するからです。

```sh
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` と口で言うのは簡単だが、これをそのままコマンドとして簡潔に書くにはどうすれば良いのだろうか？」という試行錯誤から発明されています。その詳細は以下で語られています。

https://www.tuhs.org/Archive/Documentation/OralHistory/expotape.htm

つまり、パイプ記号は into という単語の別名であり、あえていうなら前置詞です。

### コマンド同士をつなぐ「庭のホース」

パイプの考案者である Douglas McIlroy はパイプの概念を、コマンド同士をつなぐ「庭のホースのようなもの」と考えていました。

https://doc.cat-v.org/unix/pipes/

## コマンドライン引数の良い設計

コマンドライン引数の良い設計とは、**他のコマンドと組み合わせやすい設計**です。具体的には固定数の引数の後に（必要なら）**可変長の引数（複数の引数）を渡せるようにすること** です。GNU コマンドなどは、オプションを引数の最後に書くことができますが、手段の一つとして用意されているだけなので問題ありません。

```txt:一般的なコマンドの良い設計例
コマンド名 [オプション] [固定数の引数] [可変長引数]...
```

```txt:サブコマンドを使う場合の良い設計例
コマンド名 [グローバルオプション] サブコマンド [オプション] [可変長引数]...
```

コマンド名は動詞にできるのなら別にしても構いませんが、動詞にする必要はありません。実際に Unix コマンドには動詞でないものはいくつもあります。何かを実行するサブコマンドは動詞であることがよくありますが、サブサブコマンドがある場合のサブコマンドはおそらく名詞でしょう。

## さいごに

Unix コマンドの仕様が英語の文法を踏まえているかどうかなんて考えなくてよいです。少し考えば**明らかな矛盾がいくつも見つかる話**に対して、つじつまを合わせようとすることに意味はありません。これは最終的に「**Unix コマンドの文法は英語の文法を踏まえていないねという結論で終わる話**」です。昔にまだ Unix が小さかった頃は英語風の文法を採用していたけれど、多くのコマンドが作られ複数のファイルを指定するようになり、英語風の文法は破綻したので実用目的のために変化しています。