17
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

シェルスクリプトの type, command, which 等の違いと注意点

Last updated at Posted at 2021-07-25

はじめに

この記事は type, command, which 等を用途で使い分けたい人のための記事です。関連がある hashwhencewhere や紛らわしい whereiswhatiswhat についても解説しています。これらのコマンドは、コマンドの存在チェックでよく使われますが、本来の用途というものがあるわけでその違いと実際のシェルでの実装の注意点を解説しています。速度に関しては「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)を使うべきhashwhencewhichwhere は使ってはいけません。例外は posh に対応する場合で typecommand -v (-V)hash が実装されてないので which コマンドを使うか自分で実装する必要があります。typecommand -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つの実装の根本的な違いを理解しておくと、この記事の内容が理解しやすいため説明します。シェルビルトインコマンドはシェルによって実装されているためシェルの機能を認識することができます。シェルの機能というのは、シェルビルトインコマンド、シェル関数、エイリアス、シェルのキーワード(予約語)のことでシェルビルトインコマンドであればこれらを認識することができます。しかし外部コマンドの場合はシェルから起動する別のプログラムであるためシェルの機能を認識することはできません。

この記事の内容を検証する場合、外部コマンド版の typecommandhash 等の存在に気をつけてください。これらは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 シェルと完全な互換性がないので殆どの場合考慮する必要はないと思います。

whichwhere の由来?

調べていて気づいたのですが、whichwhere はおそらく csh/tcsh 由来のコマンドではないかと思っています。どちらも csh/tcsh のシェルビルトインコマンドです。wherewhich -a 相当のコマンドです(ただし csh/tcsh では which-a オプションはありません)。

zsh で whichwhere がシェルビルトインコマンドである理由は、zsh が ksh (POSIX シェル)だけでなく csh/tcsh の機能も取り込んだシェルだからでしょう。Bourne シェルと csh/tcsh が次世代の標準シェル争いをしていた古い時代では Bourne シェル では type、csh/tcsh では which を使うのがコマンドの存在チェックの定番だったのではないかと推測しています。

各コマンドの詳細

type (POSIX)

コマンドの種類を表示する

指定した単語が、シェルビルトインコマンド、シェル関数、エイリアス、キーワード(予約語)、外部コマンド(、それ以外のシェル独自の種類)のどれなのかを調べるときに使います。いずれかである場合は見つかった種類を出力し終了ステータス 0 で正常終了します。出力は「未定義の形式で出力される」のでシェルによって出力形式が異なります(外部コマンドのパスが出力に含まれることは必須ではありません)。どれにも当てはまらない場合は終了ステータス 非 0 で失敗となります。

実装に関する特記事項

POSIX で規定されており POSIX シェルではシェルビルトインとして実装されています。ただし必須ではない(XSI 拡張オプション)ので実装されていないシェルがあります。Bourne シェルでもシェルビルトインで実装されています。

POSIX (Issue 6): type

# [XSI] X/Open System Interfaces: The functionality described is
# part of the X/Open Systems Interfaces option.
type name...

POSIX (Issue 7): type

# [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 シェルでは実装されていません。

POSIX (Issue 6): command

command [-p] command_name [argument ...]

# [UP] User Portability Utilities: The functionality described is optional.
command [ -v | -V ] command_name

Issue 6 では -p-v, -V を組み合わせることができないことに注意。

POSIX (Issue 7): command

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 -vPATH 環境変数の相対パスでコマンドが見つかった場合に絶対パスを出力するように修正されました。
    • R51 より前は command -v でシェルの予約語が検索できません(type でなら可能)。
  • 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(オプションなし)の場合、シェルビルトインコマンドは実行されず必ず外部コマンドが実行されます。
  • Bourne シェル
    • 実装されていません。
  • tcsh
    • 実装されていません。

補足 dash、bash、busybox ash、mksh、zsh など多くのシェルで command -vPATH 環境変数の相対パスでコマンドが見つかった場合に相対パスで出力されてしまうという問題があります。これは絶対パスで出力するという 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 (echotest 等)は絶対パスで出力するとあるので 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 では「出力形式は指定されていない」とあるのでシェルによって異なります。ただし「その出力にパスが含まれている」と記載されています。

実装に関する特記事項

POSIX (Issue 6): hash

# [XSI] X/Open System Interfaces: The functionality described is
# part of the X/Open Systems Interfaces option.
hash [utility...]
hash -r

POSIX (Issue 7): hash

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 オプションがあります)。
    • -a オプションのみが実装されています。
  • CentOS / RedHat
    • GNU 版の which コマンド]が採用されています。
    • v2.21 時点で -a オプションは実装されていますが、-s オプションは実装されていません。
    • その他いくつかの(風変わりな)オプションが多数実装されています。(下記参照)
    • 最小構成ではインストールされません。
  • Alpine Linux / BusyBox
  • macOS
    • (おそらく)FreeBSD 版の which コマンドが採用されています。
    • -a オプションと -s オプション(標準出力に表示しない)のみが実装されています。
    • 注意 zsh のシェルビルトインの which コマンドと混同しないように注意してください。
  • FreeBSD
    • FreeBSD 版の which コマンドが採用されています。
    • -a オプションと -s オプション(標準出力に表示しない)のみが実装されています。
  • NetBSD
    • NetBSD 版の which コマンドが採用されています。
    • -a オプションと -p オプションが実装されています。
      • -p オプションは usage に表示されますが、man which には乗っておらず詳細は不明です。
  • OpenBSD
    • OpenBSD 版の which コマンドが採用されています。
    • -a オプションのみが実装されています。
  • Solaris 10
    • Solaris 版の which コマンドが採用されています(パスは /usr/bin/which)。
    • 実装は csh スクリプトです。
    • オプションはなにも実装されていません。
    • 注意 csh のシェルビルトインの which コマンドと混同しないように注意してください。
  • Solaris 11
    • GNU 版の which コマンドが採用されています(パスは /usr/bin/which)。
  • mksh
    • シェルでは実装されていませんが dot.mkshrcでシェル関数として実装するサンプルが付属しており man mksh にも記載されています(-a オプションのみが実装されています)。
  • 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.) ということなのでライセンスを気にすることなくシェルスクリプト版の実装コードとして利用することができます。これは特に typecommand -v (-V)hash に対応してない posh でコマンドの存在チェックをしたいときに便利でしょう。参考として macOS 等との互換性向上のために -s オプションが一時的に追加された時のコミットを提示します(その後、非推奨とする過程で revert されました)。

GNU which の詳細

外部コマンドでありながら、シェルのエイリアスやシェル関数を見つけることができるように設計されているようです。そのために --read-functions--read-alias を使って現在のシェルの状態を標準入力から読み取って判断する仕組みを備えています。ただしそのままでは使いづらいため man which ではシェル関数を定義する例が記載されています。この例では which と同じく GNU である bash 特有の機能を使っているので bash でしかうまく動かない可能性があります。個人的にはここまでして which コマンドでエイリアスやシェル関数を調べたいとは思いません(typecommand を使います)。過剰すぎるこのオプションが 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

コマンド検索を包括的にサポートしているコマンド

一部のシェルでは commandtypewhichwherewhence のエイリアス(または同等の実装)になっています。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 -vwhence 相当です。
    • typewhence -v のエイリアスです。
    • command -Vwhence -v 相当です。
  • mksh
    • command -vwhence 相当です(エイリアスの出力が僅かに異なる)。
    • typewhence -v (\builtin whence -v) のエイリアスです。
    • command -Vwhence -v と全く同じです。
    • which(サンプルのシェル関数)は whence -p 相当です。
  • zsh
    • command -vwhence 相当です。
    • command -Vwhence -v 相当です。
    • typewhence -v 相当です。
    • wherewhence -ca 相当です。
    • whichwhence -c 相当です。

where

指定したコマンドがある場所を全て探索する

whichPATH 環境変数から見つかった最初のコマンドだけを返すのに対して、wherePATH から見つかったすべてのコマンドを返します。実装されているシェルは 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 から分離してこの仕様だけ残したらよかったんじゃないかなと思わなくもないです。

17
16
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?