一口に「nlコマンド」と言っても様々な実装があります。機能に大きな差はありませんが、この記事ではnlの種類とその調べ方について説明していきます。
nlコマンドの種類
最初のnlコマンド
最初にnlが実装されたシステムは、1984年に発売されたAT&Tの「System V Release 2(SVR2)」のようです。FreeBSDのドキュメントにはこのような記載がありました。
HISTORY
The nl utility first appeared in AT&T System V Release 2 UNIX.
出典:https://www.freebsd.org/cgi/man.cgi?query=nl
さらには1987年、X/Open Portability Guide(issue 2)で標準化され、POSIXやSingle Unix Specificationといった後の主要な標準ドキュメントにも記載されていきます。30年以上の歴史あるコマンドですから、今回紹介する実装以外にも様々なnlが存在することでしょう。
GNU coreutils
GNU coreutilsは多くのLinuxディストリビューションで採用されているnlを含む主要なコマンドユーティリティです。他の実装に比べて、GNUによる独自の機能拡張や性能改善がされています。この拡張が互換性や移植性の問題を引き起こすこともありますが、個人的な利用において過度に気にする必要は無いでしょう。
執筆時点の最新版はv8.32で2020年3月にリリースされたものです。最近のLinuxディストリビューションでは、RHEL8やCentOS8、Ubuntu 20.04LTSではv8.30が、Ubuntu 20.10ではv8.32が採用されているようです。
BSD系(macOS、FreeBSD等)
BSD系のnlは単一の提供元が存在するわけではなく、*BSDの実装を元にAppleなどの各OSベンダーが必要に応じた改変を加え提供しているnlの総称的なものになります。もちろん細かな挙動は各々の実装で異なる可能性がありますし、プロプライエタリな実装もあります。
ちなみにAppleのSource Browserによると、macOSではNetBSDの実装が使われているようです。
busybox
ルーターなどのLinux組み込み機器では、コマンドユーティリティにbusyboxが採用されていることがあります。busyboxは単一の実行ファイルで、呼び出されたときのコマンド名に応じて様々なコマンドの動作が可能な特殊なソフトウェアです。もちろんnlの機能も内包されています。実行ファイルのサイズがとても小さいので、組み込み機器など記憶領域に制約がある環境で採用されています。
種類やバージョンの調べ方
--versionオプション
--versionオプションでコマンドのバージョンを見ることができます。このとき著作権に関する情報も出力されるので、どんなnlなのかを知ることができます。しかしcoreutils以外のnlの実装では、--versionオプションに対応しておらずエラーと簡単な使い方だけが表示されてバージョンが判明しないこともあります。
$ nl --version
nl (GNU coreutils) 8.30
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Scott Bartram and David MacKenzie.
Ubuntuのnlでは、--versionオプションを使うことで、GNU coreutilsであることがわかりました。
% nl --version
nl: illegal option -- -
usage: nl [-p] [-b type] [-d delim] [-f type] [-h type] [-i incr] [-l num]
[-n format] [-s sep] [-v startnum] [-w width] [file]
一方macOSのnlでは、--versionオプションをサポートしていないので、一意に識別することはできません。
Manpage
Manpageの記述を見ることでも、nlの種類を判断することができます。Manpageが存在しない環境では表示されませんが、ほとんどのLinuxやmacOSで表示できるはずです。man nlと実行すればnlのManpageを読むことができます。著作権やバージョンの記述は下の方に記載されていますので、tailを用いて最後の10行を表示してみましょう。
$ man nl | tail -n 10
Copyright © 2018 Free Software Foundation, Inc. License GPLv3+: GNU
GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
SEE ALSO
Full documentation at: <https://www.gnu.org/software/coreutils/nl>
or available locally via: info '(coreutils) nl invocation'
GNU coreutils 8.30 September 2019 NL(1)
こちらを見てもUbuntuのnlはcoreutilsであることが確認できました。
% man nl | tail -n 10
STANDARDS
The nl utility conforms to IEEE Std 1003.1-2001 (``POSIX.1'').
HISTORY
The nl utility first appeared in AT&T System V Release 2 UNIX.
BUGS
Input lines are limited to LINE_MAX (2048) bytes in length.
BSD January 26, 2005 BSD
macOSはManpageのフッターを見ることで、BSD系のnlであることが確認できました。
コマンドの識別
コマンドは絶対パスではなくコマンド名だけで呼び出すことがほとんどです。しかし一つの環境で複数のnlがインストールされている場合など、どのコマンドが呼び出されているのかわからなくなることがあります。このような場合にはwhichを利用することで、デフォルトでどのコマンドが実行されているのかを調べることができます。
$ which nl
/usr/bin/nl
これで/usr/bin/nlが実行されることがわかります。さらに詳細を知りたい場合は、先ほどの例にならい/usr/bin/nl --versionを実行してバージョンなどを調べてみると良いでしょう。
実行されるコマンドはシェルの環境変数である$PATHに基づいて選ばれています。詳しくは説明しませんが、この環境変数を変更することで、実行するデフォルトのコマンドを変更することができます。
補足
この記事シリーズでは特に断りのない限り、GNU coreutilsのnlを使用します。
macOSでcoreutilsのnlを利用したい場合は、brewなどを利用してインストールできます。デフォルトではgnlという名前のコマンドとしてインストールされ、もとのBSD系のnlと使い分けることができます。他のcoreutilsのコマンドも頭にgをつければ使うことができます。
% brew install coreutils
(略)
% gnl --version
(略)