はじめに
この記事は type
, command
, which
等を用途で使い分けたい人のための記事です。関連がある hash
、whence
、where
や紛らわしい whereis
、whatis
、what
についても解説しています。これらのコマンドは、コマンドの存在チェックでよく使われますが、本来の用途というものがあるわけでその違いと実際のシェルでの実装の注意点を解説しています。速度に関しては「Bashでコマンドの存在チェックはwhichよりhashの方が良いかも→いやtypeが最強→command -vも」ですでに記事があるので特に調べませんが、個人的には「シェルビルトインコマンドの方が速い」という考え方だけで十分だと思っています。
補足 この記事の Bourne シェル とは Solaris 10 の /bin/sh
のことです。その他の(商用)UNIX の Bourne シェルでは検証していません。また POSIX シェルとは dash, busybox ash, bash, ksh88, ksh93, mksh, posh, yash, zsh のことでこれらのシェルで確認しています。バージョン番号が明記されてないものはすべてのバージョンに当てはまると考えてください。
コマンドの存在チェックをしたい場合
各コマンドの解説が目的なので、記事の趣旨とは異なりますが「(POSIX シェルで)コマンドの存在チェックに何を使うべきか?」の答えが知りたい人のために書いておくとほとんどの POSIX シェルで使える type
または command -v (-V)
を使うべきで hash
、whence
、which
、where
は使ってはいけません。例外は posh に対応する場合で type
、command -v (-V)
、hash
が実装されてないので which
コマンドを使うか自分で実装する必要があります。type
か command -v (-V)
かはどちらでも良いですが、私は短い type
の方を使っています。詳細は記事内容を参照してください。
外部コマンドのパスを知りたい場合
POSIX 準拠の方法で外部コマンドのパスを調べる場合、一般的には command -v
を使うというのが答えですが、同名のシェルビルトインコマンド、シェル関数、エイリアスがある場合は、外部コマンド版があったとしてもそのパスを取得することはできません。単にコマンドがどのパスにあるかを全て見たいだけなら which -a
がおすすめです。ただし zsh ではシェルビルトインコマンド等が含まれます。
どうあっても(PATH
を検索して最初に見つけた)外部コマンドのパスが知りたいということはあまりないと思うのですが、実はこれを知るための確実で可搬性がある簡単な方法はありません。以下がその理由です。
-
type
- 出力形式は POSIX で規定されておらずシェル毎に異なります。
- 同名のシェルビルトインコマンド、シェル関数、エイリアスがある場合は外部コマンドのパスは出力されません。
-
command
-
-V
の出力形式は POSIX で規定されておらずシェル毎に異なります。(実際のシェルでは殆どの場合type
と同じ内容です。) -
-v
は同名のシェルビルトインコマンド、シェル関数、エイリアスがある場合は外部コマンドのパスは出力されません。 -
-p
を-v
と併用した場合でもシェルビルトインコマンドが優先されコマンド名のみが出力され外部コマンドのパスは出力されません。
-
-
which
- POSIX で規定されていないコマンドで、インストールされていない環境もあります。
- zsh ではシェルビルトインであり、同名のシェルビルトインコマンド、シェル関数、エイリアスがある場合は外部コマンドのパスは出力されません。
(外部コマンド版の)which
コマンドがインストールされている環境が前提であれば env which
(または commnad -p which
)とすることで PATH
から最初に見つけた外部コマンドのパスを取得することができますが、which
コマンドが入ってない場合でも確実に外部コマンドのパスを知りたい場合は自分で実装する必要があります(which
参照)。
シェルビルトインコマンドと外部コマンドの違い
コマンドはシェルに内蔵されている場合(シェルビルトインコマンド)とシェル以外で実装されているコマンド(外部コマンド)の2種類があります。この2つの実装の根本的な違いを理解しておくと、この記事の内容が理解しやすいため説明します。シェルビルトインコマンドはシェルによって実装されているためシェルの機能を認識することができます。シェルの機能というのは、シェルビルトインコマンド、シェル関数、エイリアス、シェルのキーワード(予約語)のことでシェルビルトインコマンドであればこれらを認識することができます。しかし外部コマンドの場合はシェルから起動する別のプログラムであるためシェルの機能を認識することはできません。
この記事の内容を検証する場合、外部コマンド版の type
、command
、hash
等の存在に気をつけてください。これらはPOSIX に準拠した動作をするにはシェルビルトインでなければ実現不可能なのですが、それでも外部コマンド版が存在することがあります(macOS 等)。外部コマンドが存在することによる勘違いの一例をあげると、macOS の tcsh で type type
を実行するとシェルビルトインコマンドであると出力されます。しかしながら type
コマンドは tcsh のシェルビルトインコマンドではありません。これは外部コマンド版の type
= macOS では /bin/sh
(bash) で実行されるシェルスクリプトを実行した結果が出力されているからです。
各コマンドの実装状況の概要を以下に示します。
コマンド | POSIX | ビルトインされているシェル | 外部コマンド版 |
---|---|---|---|
type | YES (XSI) | POSIX シェル(posh を除く)、Bourne シェル | 一部の環境で存在する |
command | YES (必須、Issue6 では一部 UP) | POSIX シェル(posh は一部の機能がない) | 一部の環境で存在する |
hash | YES (XSI) | POSIX シェル(posh を除く) | 一部の環境で存在する |
whence | NO | ksh88、ksh93、pdksh、mksh、zsh | 見かけない |
which | NO | tcsh (csh)、zsh | 環境次第でまちまち |
where | NO | tcsh (csh)、zsh | 見かけない |
XSI と UP は POSIX の仕様上はオプションとなっているものです(下記参照)。仕様上は command
の方が POSIX で必須となっているため type
より良いように見えますが、ほとんどの POSIX シェルで両方ともシェルビルトインで実装されているので変わりません。例外は posh ですが posh の場合はオプション機能が実装されていません。Bourne シェルを考慮するなら type
の方が良いと思いますが Bourne シェル は(古い商用の) UNIX で使われていたシェルで、算術式展開などが使えない等、POSIX シェルと完全な互換性がないので殆どの場合考慮する必要はないと思います。
which
と where
の由来?
調べていて気づいたのですが、which
と where
はおそらく csh/tcsh 由来のコマンドではないかと思っています。どちらも csh/tcsh のシェルビルトインコマンドです。where
は which -a
相当のコマンドです(ただし csh/tcsh では which
に -a
オプションはありません)。
zsh で which
と where
がシェルビルトインコマンドである理由は、zsh が ksh (POSIX シェル)だけでなく csh/tcsh の機能も取り込んだシェルだからでしょう。Bourne シェルと csh/tcsh が次世代の標準シェル争いをしていた古い時代では Bourne シェル では type
、csh/tcsh では which
を使うのがコマンドの存在チェックの定番だったのではないかと推測しています。
各コマンドの詳細
type (POSIX)
コマンドの種類を表示する
指定した単語が、シェルビルトインコマンド、シェル関数、エイリアス、キーワード(予約語)、外部コマンド(、それ以外のシェル独自の種類)のどれなのかを調べるときに使います。いずれかである場合は見つかった種類を出力し終了ステータス 0
で正常終了します。出力は「未定義の形式で出力される」のでシェルによって出力形式が異なります(外部コマンドのパスが出力に含まれることは必須ではありません)。どれにも当てはまらない場合は終了ステータス 非 0
で失敗となります。
実装に関する特記事項
POSIX で規定されており POSIX シェルではシェルビルトインとして実装されています。ただし必須ではない(XSI 拡張オプション)ので実装されていないシェルがあります。Bourne シェルでもシェルビルトインで実装されています。
# [XSI] X/Open System Interfaces: The functionality described is
# part of the X/Open Systems Interfaces option.
type name...
# [XSI] X/Open System Interfaces: The functionality described is
# part of the X/Open Systems Interfaces option.
type name...
- mksh
-
\builtin whence -v
のエイリアスです。以前(R50dあたり?)はwhence -v
のエイリアスでした。
-
- ksh93
-
whence -v
のエイリアスです。ksh93u+m ではシェルビルトインです。
-
- posh
- `実装されていません(XSI 拡張のオプションのため?)。
- zsh
-
whence -v
相当です(ただしエイリアスではない)。
-
- macOS
-
/usr/bin/type
が存在しますが、/bin/sh
で実行されるシェルスクリプトなので、実際には bash で実行された結果が表示されます。
-
- FreeBSD
-
/usr/bin/type
が存在しますが、/bin/sh
で実行されるシェルスクリプトなので、実際には FreeBSD sh で実行された結果が表示されます。
-
- Solaris 10
-
/usr/bin/type
が存在しますが、/bin/ksh -p
で実行されるシェルスクリプトなので、実際には ksh88 で実行された結果が表示されます。 -
/usr/xpg4/bin/type
には/usr/xpg4/bin/sh -p
(ksh93u+) で実行されるシェルスクリプト版もあります。
-
- Solaris 11
-
/usr/bin/type
が存在しますが、実装はtype
が実行されるようにビルドされた ksh93u+ のようです。 -
/usr/xpg4/bin/type
には/usr/xpg4/bin/sh -p
(ksh93u+) で実行されるシェルスクリプト版もあります。
-
- tcsh
- 実装されていません。
command (POSIX)
コマンドの実行、またはコマンドのパスや種類の表示
シェル関数の探索をバイパスし、シェルビルトインコマンドまたは外部コマンドを実行したり、コマンドのパスや種類を表示するコマンドです。-v
オプションの出力は処理しやすいように POSIX で定義されており、-V
は人間にとって読みやすい形式で表示されます(type
の出力と同等)。
実装に関する特記事項
POSIX で規定されており POSIX シェルではシェルビルトインとして実装されています。ただし -v
, -V
オプションは必須ではない(UP オプション)ので実装されていないシェルがあります。また Bourne シェルでは実装されていません。
command [-p] command_name [argument ...]
# [UP] User Portability Utilities: The functionality described is optional.
command [ -v | -V ] command_name
Issue 6 では -p
と -v
, -V
を組み合わせることができないことに注意。
command [-p] command_name [argument...]
command [-p][-v|-V] command_name
-v
(-V
) を指定した場合は POSIX の仕様では複数のコマンドを指定できないことに注意。複数のコマンドを指定した場合やコマンドが見つからなかった場合の終了ステータスはシェルによって異なります。
- dash
-
command -v
またはcommand -V
は一つのコマンドしか調べられません。
-
- BusyBox ash
-
command -v
またはcommand -V
は一つのコマンドしか調べられません。
-
- bash
-
command -v
またはcommand -V
で複数のコマンドを指定した場合、少なくとも一つのコマンドが見つかった場合に終了ステータスは0
になります(POSIX モードでも同じ)。
-
- ksh88
-
-p
オプションと-v
,-V
を組み合わせることができません。Issue 6 の定義は最初の POSIX シェルである ksh88 の仕様に基づくものだと思われます。 - デフォルトで
command='command '
のエイリアスが定義されています(最後の空白によりcommand
に続く単語もエイリアス展開が行われる)。
-
- ksh93
- デフォルトで
command='command '
のエイリアスが定義されています(最後の空白によりcommand
に続く単語もエイリアス展開が行われる)。 - ksh93u+m では上記のエイリアスは定義されていません。
- デフォルトで
- mksh
- R59c-1 では
command -v
でPATH
環境変数の相対パスでコマンドが見つかった場合に絶対パスを出力するように修正されました。 - R51 より前は
command -v
でシェルの予約語が検索できません(type
でなら可能)。
- R59c-1 では
- posh
-
-v
、-V
オプションは実装されていません(Issue 6 では UP オプションのため?)。Issue 7 では必須ですが追尾できていません。
-
- yash
-
command -v
はシェルビルトインコマンドがある場合でも外部コマンドのパスを優先して出力します(下記 補足2 参照)。
-
- zsh
- 5.2 系とそれより前のバージョンでは
-p
オプションと-v
,-V
を組み合わせることができません(Issue 6 参照、5.3のリリースは 2016-12-12)。 - 5.3 系とそれより前のバージョンでは
\command -v
がエラーになります。 -
command
(オプションなし)の場合、シェルビルトインコマンドは実行されず必ず外部コマンドが実行されます。
- 5.2 系とそれより前のバージョンでは
- Bourne シェル
- 実装されていません。
- tcsh
- 実装されていません。
補足 dash、bash、busybox ash、mksh、zsh など多くのシェルで command -v
で PATH
環境変数の相対パスでコマンドが見つかった場合に相対パスで出力されてしまうという問題があります。これは絶対パスで出力するという POSIX の仕様に準拠してないと思われます(これはもう POSIX 側を修正すべきな気がする)。
Utilities, regular built-in utilities, command_names including a character, and any implementation-defined functions that are found using the PATH variable (as described in Command Search and Execution), shall be written as absolute pathnames.
補足2 yash では他のシェルと異なり command -v echo
で /bin/echo
と出力されますが、上記の POSIX の仕様より regular built-in utilities (echo
、test
等)は絶対パスで出力するとあるので yash の動作が正しいと思われます。(参考)
builtin command
について
https://please-sleep.cou929.nu/check-command-existence-on-shellscript.html より
rvm がこういうふうにやっていた. なぜ builtin command というふうにわざわざやっているのかがよくわからない. command っていうコマンドがビルトイン以外にもあってかぶるケースがあるのかな.
少し気になったので調べた所、rvm が使用している SM Framework(これが何なのかは分かってない)が、command
コマンドをシェル関数で再定義しているからのようです。一応本来の command
コマンドと互換性を持たせつつ拡張しているようですが何かしらの問題があったのでしょう。普通はわざわざ builtin
をつける必要はありません。
hash (POSIX 準拠)
ハッシュテーブルの内容の表示、コマンドの追加、内容の削除を行う
PATH
環境変数からコマンドを探索する処理は時間ががかかるため、シェルはコマンド名とパスの対応をハッシュテーブルに格納します。この処理は通常コマンド実行時に自動的に行われます。また環境変数 PATH
に値を代入するとハッシュテーブルはクリアされます(hash -r
相当)これらの処理を手動で行うのが hash
コマンドです。本来はハッシュテーブルの操作用のコマンドなので用途通りの使い方ではありませんし、mksh と ksh ではコマンドが見つからない場合でもエラーにならないのでコマンドの存在チェックに使ってはいけません。
引数がない場合はハッシュされたコマンド一覧が出力されますが、POSIX では「出力形式は指定されていない」とあるのでシェルによって異なります。ただし「その出力にパスが含まれている」と記載されています。
実装に関する特記事項
# [XSI] X/Open System Interfaces: The functionality described is
# part of the X/Open Systems Interfaces option.
hash [utility...]
hash -r
hash [utility...]
hash -r
- ksh
- 指定したコマンドが見つからない場合も正常終了します(終了ステータス
0
)。
- 指定したコマンドが見つからない場合も正常終了します(終了ステータス
- mksh
- 指定したコマンドが見つからない場合も正常終了します(終了ステータス
0
)。
- 指定したコマンドが見つからない場合も正常終了します(終了ステータス
- posh
- `実装されていません(XSI 拡張のオプションのため?)。
- tcsh
- 実装されていません。
補足 ksh と mksh では指定したコマンドが見つからない場合も正常終了しますが、POSIX の仕様では「見つからない場合は失敗である」とは書いていないようなので POSIX の仕様には違反していないと思われます。
which
指定したコマンドの場所を探索する
指定したコマンドの場所を探索するためのコマンドです。POSIX では規定されておらずデフォルトでインストールされていない環境もあります。基本的に外部コマンドとして実装されており OS によって異なる実装を使用していますが、zsh ではシェルビルトインコマンドとして実装されているので注意が必要です。具体的には macOS (デフォルトシェルが zsh に変わった)でシェルから実行した場合とシェルスクリプトから実行した場合で出力結果が異なる場合があります。外部コマンドの which
ではシェルのキーワード(予約語)やシェル関数を見つけることができませんが、zsh のシェルビルトインコマンドでは見つけることができてしまうからです(例 zsh では which "[["
が shell reserved word
と表示される)。-a
オプションは多くの環境で使えますが、Solaris 10(古い UNIX?)では実装されていません。その他のオプションは移植性が低いです。個人的な意見ではwhich コマンドはシェルスクリプトでは使うのはやめ、手作業でコマンドの場所を調べたいときに使うものと考えたほうが良いと思います。
実装に関する特記事項
- Debian / Ubuntu
-
debianutils 版の
which
コマンドが採用されています。 - POSIX 準拠のシェルスクリプトで実装されています。
- Debian 3.0 までは bash スクリプトで
type -p
相当でした(bash のtype
には-a
オプションがあります)。
- Debian 3.0 までは bash スクリプトで
-
-a
オプションのみが実装されています。
-
debianutils 版の
- CentOS / RedHat
-
GNU 版の
which
コマンド]が採用されています。 - v2.21 時点で
-a
オプションは実装されていますが、-s
オプションは実装されていません。 - その他いくつかの(風変わりな)オプションが多数実装されています。(下記参照)
- 最小構成ではインストールされません。
-
GNU 版の
- Alpine Linux / BusyBox
-
BusyBox アプレット版の
which
コマンドが採用されています。 - v1.33.1 時点で
-a
オプションのみが実装されています(ただし usage に表示されていません)。
-
BusyBox アプレット版の
- macOS
- (おそらく)FreeBSD 版の
which
コマンドが採用されています。 -
-a
オプションと-s
オプション(標準出力に表示しない)のみが実装されています。 - 注意 zsh のシェルビルトインの
which
コマンドと混同しないように注意してください。
- (おそらく)FreeBSD 版の
- FreeBSD
- FreeBSD 版の
which
コマンドが採用されています。 -
-a
オプションと-s
オプション(標準出力に表示しない)のみが実装されています。
- FreeBSD 版の
- NetBSD
- NetBSD 版の
which
コマンドが採用されています。 -
-a
オプションと-p
オプションが実装されています。-
-p
オプションは usage に表示されますが、man which
には乗っておらず詳細は不明です。
-
- NetBSD 版の
- OpenBSD
- OpenBSD 版の
which
コマンドが採用されています。 -
-a
オプションのみが実装されています。
- OpenBSD 版の
- Solaris 10
- Solaris 版の
which
コマンドが採用されています(パスは/usr/bin/which
)。 - 実装は csh スクリプトです。
- オプションはなにも実装されていません。
- 注意 csh のシェルビルトインの
which
コマンドと混同しないように注意してください。
- Solaris 版の
- Solaris 11
- GNU 版の
which
コマンドが採用されています(パスは/usr/bin/which
)。
- GNU 版の
- mksh
- シェルでは実装されていませんが dot.mkshrcでシェル関数として実装するサンプルが付属しており
man mksh
にも記載されています(-a
オプションのみが実装されています)。
- シェルでは実装されていませんが dot.mkshrcでシェル関数として実装するサンプルが付属しており
- zsh
- シェルビルトインコマンドです。
-
whence -c
相当です(エイリアスではない)。 -
whence
コマンドのオプションが使用できますが、which
コマンドのオプションとは互換性がありません。-a
オプションのみwhich
コマンドと同じ意味です。
- tcsh
- シェルビルトインコマンドです。
- オプションはなにも実装されていません。
debianutils which の補足
Debian で現在採用されている debianutils which はシェルスクリプトで実装されています。最近のコミットを見る限り、POSIX で定義されている type
または command -v
を使うことを推奨し、debianutils 版の which
コマンドは Debian 11 を最後に非推奨となるようです(おそらく別パッケージへ移行)。現在は最小構成でもインストールされていますが、Debian 12 以降は最小構成ではインストールされなくなる可能性があるのではないかと思っています。(この記事を書いているのは Debian 11 リリース前です。)
debianutils which のライセンスによると Public Domain (which is in the public domain.
) ということなのでライセンスを気にすることなくシェルスクリプト版の実装コードとして利用することができます。これは特に type
、command -v (-V)
、hash
に対応してない posh でコマンドの存在チェックをしたいときに便利でしょう。参考として macOS 等との互換性向上のために -s
オプションが一時的に追加された時のコミットを提示します(その後、非推奨とする過程で revert されました)。
GNU which の詳細
外部コマンドでありながら、シェルのエイリアスやシェル関数を見つけることができるように設計されているようです。そのために --read-functions
や --read-alias
を使って現在のシェルの状態を標準入力から読み取って判断する仕組みを備えています。ただしそのままでは使いづらいため man which
ではシェル関数を定義する例が記載されています。この例では which
と同じく GNU である bash 特有の機能を使っているので bash でしかうまく動かない可能性があります。個人的にはここまでして which
コマンドでエイリアスやシェル関数を調べたいとは思いません(type
や command
を使います)。過剰すぎるこのオプションが Debian が GNU which を採用しなかった理由かもしれません。
Usage: which [options] [--] COMMAND [...]
Write the full path of COMMAND(s) to standard output.
--version, -[vV] Print version and exit successfully.
--help, Print this help and exit successfully.
--skip-dot Skip directories in PATH that start with a dot.
--skip-tilde Skip directories in PATH that start with a tilde.
--show-dot Don't expand a dot to current directory in output.
--show-tilde Output a tilde for HOME directory for non-root.
--tty-only Stop processing options on the right if not on tty.
--all, -a Print all matches in PATH, not just the first
--read-alias, -i Read list of aliases from stdin.
--skip-alias Ignore option --read-alias; don't read stdin.
--read-functions Read shell functions from stdin.
--skip-functions Ignore option --read-functions; don't read stdin.
Recommended use is to write the output of (alias; declare -f) to standard
input, so that which can show aliases and shell functions. See which(1) for
examples.
If the options --read-alias and/or --read-functions are specified then the
output can be a full alias or function definition, optionally followed by
the full path of each command used inside of those.
Report bugs to <which-bugs@gnu.org>.
alias which='alias | which -i'
which() { declare -f | which --read-functions $@ }
export -f which
補足 declare
は POSIX で規定されておらず export -f
が使えるのは bash のみ
EXAMPLE
The recommended way to use this utility is by adding an alias (C shell)
or shell function (Bourne shell) for which like the following:
[ba]sh:
which ()
{
(alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@
}
export -f which
[t]csh:
alias which 'alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
whence
コマンド検索を包括的にサポートしているコマンド
一部のシェルでは command
、type
、which
、where
は whence
のエイリアス(または同等の実装)になっています。ksh88、ksh93、pdksh、mksh、zsh で実装されています。一部のシェルでしか使えないため必要がない限り使わないほうが良いです。以下は man ksh
からの抜粋です。最も古い ksh88 では -p
オプションと -v
オプションしか存在しませんでした。
ksh88 (Solaris 10)
whence [ -pv ] name ...
For each name, indicates how it would be interpreted if used as a command name.
The -v flag produces a more verbose report.
The -p flag does a path search for name even if name is an alias, a function, or a reserved word.
ks93
whence [ -afpv ] name ...
For each name, indicate how it would be interpreted if used as a command name.
The -v option produces a more verbose report. The -f option skips the search for functions.
The -p option does a path search for name even if name is an alias, a function, or a reserved word.
The -p option turns off the -v option. The -a option is similar to the -v option
but causes all interpretations of the given name to be reported.
pdksh
whence [-pv] [name ...]
For each name, the type of command is listed (reserved word, built-in, alias, function, tracked
alias or executable). If the -p option is used, a path search done even if name is a reserved word,
alias, etc. Without the -v option, whence is similar to command -v except that whence will find
reserved words and won't print aliases as alias commands; with the -v option, whence is the same as
command -V. Note that for whence, the -p option does not affect the search path used, as it does for
command. If the type of one or more of the names could not be determined, the exit status is non-zero.
mksh
whence [-pv] [name ...]
(regular) Without the -v option, it is the same as command -v, except aliases are printed as their
definition only. With the -v option, it is exactly identical to command -V. In either case, with
the -p option the search is restricted to the (current) PATH.
zsh
whence [ -vcwfpamsS ] [ -x num ] name ...
For each name, indicate how it would be interpreted if used as a command name.
If name is not an alias, built-in command, external command, shell function, hashed command, or a
reserved word, the exit status shall be non-zero, and -- if -v, -c, or -w was passed -- a message
will be written to standard output. (This is different from other shells that write that message
to standard error.)
whence is most useful when name is only the last path component of a command, i.e. does not include
a `/'; in particular, pattern matching only succeeds if just the non-directory component of the
command is passed.
詳細なオプションの説明は省略。man を参照してください。
実装に関する特記事項
- ksh93
-
command -v
はwhence
相当です。 -
type
はwhence -v
のエイリアスです。 -
command -V
はwhence -v
相当です。
-
- mksh
-
command -v
はwhence
相当です(エイリアスの出力が僅かに異なる)。 -
type
はwhence -v
(\builtin whence -v
) のエイリアスです。 -
command -V
はwhence -v
と全く同じです。 -
which
(サンプルのシェル関数)はwhence -p
相当です。
-
- zsh
-
command -v
はwhence
相当です。 -
command -V
はwhence -v
相当です。 -
type
はwhence -v
相当です。 -
where
はwhence -ca
相当です。 -
which
はwhence -c
相当です。
-
where
指定したコマンドがある場所を全て探索する
which
が PATH
環境変数から見つかった最初のコマンドだけを返すのに対して、where
は PATH
から見つかったすべてのコマンドを返します。実装されているシェルは zsh と tcsh
(csh) だけで外部コマンド版は(私が知る限り)ありません。殆どの which
コマンドは -a
オプションを実装しており、これを where
の代わりに使うことができます。そのため where
コマンドを使うのは tcsh を使うときぐらいでしょう。
実装に関する特記事項
- zsh
- シェルビルトインコマンドです。
-
whence -ca
相当です。
- tcsh (csh)
- シェルビルトインコマンドです。
- オプションはなにも実装されていません。
余談ですが Windows には where.exe
コマンドがありますが機能は全く異なります。cygwin や msys だと Windows版の where.exe
が(拡張子なしで)実行できてしまうので注意が必要です。
紛らわしい名前のコマンド達
whereis
コマンドだけではなく man ページや ソースコードのパスも検索します。ただし macOS / BSD 系では、コマンドのパスを検索するだけの機能しか持ってないように思えます。検索パスも環境変数 PATH
ではなく sysctl user.cs_path
などを使うようです。開発者のための検索コマンドとして作られたのでしょうか? ちなみに man ページのパスは man --path コマンド
で調べることができます。
whatis
コマンドと簡単な説明を検索して表示するコマンドです。以下のような出力が得られます。
$ whatis date
cal(1), ncal(1) - displays a calendar and the date of Easter
date(1) - display or set date and time
iwidgets_datefield(n), iwidgets::datefield(n) - Create and manipulate a date field widget
gdate(1), date(1) - print or set the system date and time
what
what
はPOSIX で規定されていますが、これは(もはや使われていない)バージョン管理システムの SCCS 関連のコマンドの一つで、コマンドの識別文字列を表示するためのまったく関係ないコマンドです。以下のような出力が得られます。
$ what /bin/ls
/bin/ls
PROGRAM:ls PROJECT:file_cmds-321.100.11
Copyright (c) 1989, 1993, 1994
PROGRAM:ls PROJECT:file_cmds-321.100.11
Copyright (c) 1989, 1993, 1994
実行ファイル(バイナリ or スクリプト)の中に @(#)
で始まる文字を入れておくと、その部分をコマンドの識別文字列として表示することができます。macOS などでは ls
コマンドなど全てではないですが今も識別文字列が埋め込まれており what
コマンドでコマンドの情報を見ることができます。識別文字列が埋め込まれているかはコマンド次第です。これはこれで便利なので SCCS から分離してこの仕様だけ残したらよかったんじゃないかなと思わなくもないです。