実行可能ファイルへのパスを見つけたり、Unixシェルにコマンド名を入力したりすると、何が起こるのかを判断するためのさまざまなユーティリティ(、、、、、など)がwhich
あります。type
command
whence
where
whereis
whatis
hash
which
私たちはこれを避けるべきだと言うことをよく聞きます。なぜ?代わりに何を使うべきですか?
答え1
あなたが知りたくないと思ったことはすべて次のとおりです。
一般化する
Bourneに似たシェルスクリプトから実行可能ファイルのパス名を取得するには(いくつかの注意事項があります、以下を参照)。
ls=$(command -v ls)
特定のコマンドが存在することを確認するには、次のようにします。
if command -v given-command > /dev/null; then
echo given-command is available
else
echo given-command is not available
fi
Bourneのような対話型シェルのプロンプトで:
type ls
このwhich
コマンドはCシェルの破壊的な遺産であり、Bourneのようなシェルに単独で置くのが最善です。
はい
この情報をスクリプトの一部として見つけることと、シェルプロンプトで対話的に見つけることには違いがあります。
シェルプロンプトで一般的なユースケースは次のとおりです。このコマンドは奇妙に動作します。正しいコマンドを使用していますか?私がこれを入力している間、一体何が起こっているのでしょうかmycmd
?どんな内容なのか、もう少し詳しく調べてもいいですか?
この場合、実際にコマンドを呼び出すよりも、コマンドが呼び出されたときにシェルが何をするのかを知りたいです。
シェルスクリプトではかなり異なる傾向があります。シェルスクリプトで単にコマンドを実行したい場合は、コマンドがどこにあるのか、何かを知りたい理由はありません。一般的に知りたいのは実行可能ファイルへのパスであるため、そのファイルからより多くの情報を取得できます(たとえば、そのファイルに関連する他のファイルのパスまたはそのパス情報から実行可能ファイルの内容を読み取ることができます)。
インタラクティブな方法で次のことを知りたい場合もあります。みんなmy-cmd
このように、システム(スクリプト)で使用できるコマンドはほとんどありません。
利用可能なほとんどのツール(しばしばそのような場合)は、対話型で使用するように設計されています。
歴史
まず、少しの歴史です。
1970年代後半まで、初期のUnixシェルには機能やエイリアスはありませんでした。エイリアスは1978年頃に導入されました(最初に紹介されましたが$PATH
)。csh
csh
解放、1979年2BSD
5月).cshrc
カスタムシェルに対しても処理されます(たとえば、各シェルはcsh
スクリプト.cshrc
のようにインタラクティブでない場合も読み取られます)。
rc
Bourneシェルは1979年初頭にUnix V7で初めてリリースされましたが、機能サポートははるかに後で追加されました(1984年SVR2で)、いずれの場合もいくつかのファイルがありませんでした(.profile
非シェル環境設定用)それ自体)。
csh
インタラクティブな使用に便利で、より多くの機能を追加するため、Bourneシェルよりも人気があります(構文はBourneシェルよりはるかに悪いです)。
3BSD
(1980)ではwhich
cshスクリプトcsh
ユーザーが実行可能ファイルを識別するのを助けるために追加されたこのスクリプトwhich
は、今日多くの市販のUnices(Solaris、HP / UX、AIX、またはTru64など)で見つけることができるスクリプトとほとんど変わりません。
スクリプトは、ユーザーのコマンド~/.cshrc
(呼び出しを使用しない限り、すべてのスクリプトと同様)を読み取り、エイリアスリストとcsh
(保持されている配列に基づいて)csh -f
提供されたコマンド名を探します。$path
csh
$PATH
ここにあります:which
最初のものは当時最も人気のあるシェルでした(csh
90年代半ばまでまだ人気がありました)、これが本に書かれていて広く使われている主な理由です。
csh
ユーザーにとっても、which
cshスクリプトが必ずしも正しい情報を提供するわけではありません。~/.cshrc
後でプロンプトで定義したり、source
別のファイルを指定してエイリアスをインポートしたりするのではなく、で定義されたエイリアスをインポートしcsh
(良い考えではありませんが)、PATH
再定義することができます~/.cshrc
。
which
Bourne シェルでコマンドを実行すると、 で定義されたエイリアスを探すことができますが、~/.cshrc
エイリアスを使用せずにエイリアスがない場合csh
でも正しい答えを得ることができます。
1984年になると、組み込みコマンドによりSVR2のBourneシェルに同様の機能が追加されましたtype
。 (外部スクリプトではなく)組み込まれているという事実はできるシェルの内部にアクセスできるので、正しい情報(ある程度)を提供します。
初期コマンドは、コマンドが見つからない場合に失敗した終了状態を返さないという点で、type
スクリプトと同様の問題を経験しました。また、実行ファイルの場合は、代わりに同様のものを出力するのwhich
とは異なり、スクリプトで使用するのは簡単ではありません。which
ls is /bin/ls
/bin/ls
Unixバージョン8(一般には公開されていません)のBourneシェルに組み込まれている関数のtype
名前が変更され、whatis
引数と印刷関数の定義も報告するように拡張されました。また、type
名前が見つからないときに失敗が返されない問題を解決します。
rc
、Plan9(ワンタイムUnix以降)シェル(およびakanga
などの派生製品es
)whatis
も使用できます。
sh
80年代半ばに開発されたが、1988年以前には広く使用されていなかったKornシェル(POSIX定義の基礎となるサブセット)csh
は、Bourneシェルの上に多くの機能(ラインエディタ、エイリアス...)を追加しました。これには、いくつかのオプション(同様に詳細な出力を提供し、実行可能ファイルのみを検索(別名/関数の代わりに...))を使用する独自の組み込みwhence
関数()が追加されます。type
-v
type
-p
AT&TとBerkeleyとの著作権紛争と同時に一部フリーソフトウェアシェルの実装は1980年代後半と1990年代初頭に登場しました。 Almquistシェル(BSDのBourneシェルに代わるもの)ash
(FSFスポンサー)のすべてのパブリックドメインの実装は、1989年から1991年の間に登場しました。ksh
pdksh
bash
zsh
AshはBourneシェルを置き換えることを意図していましたが、type
ずっと後で(NetBSD 1.3とFreeBSD 2.3で)組み込み機能はありませんでしたhash -v
。ただし、OSF / 1にはOSFまで常に0を返す組み込み機能が/bin/sh
ありました。type
/ 1 v3.x。bash
何も追加されていませんが、パス( like )とレポートを印刷するオプションがwhence
追加されました。-p
type
type -p
whence -p
-a
みんな一致するコマンド。 s -likeコマンドがtcsh
組み込まれてwhich
追加されました。すべて。where
bash
type -a
zsh
Shell fish
(2005)では、コマンドがtype
関数として実装されています。
同時に、cshスクリプトはwhich
NetBSDから削除され(tcshに組み込まれていて他のシェルではあまり使用されていないため)、機能が追加されました(呼び出されたwhereis
とき)。 OpenBSDとFreeBSDではこれもCで書かれています。which
whereis
which
$PATH
which
$PATH
実装する
さまざまな Unices には、コマンドの数十種類の構文とwhich
動作の実装があります。
tcsh
Linuxでは、(およびの組み込み実装に加えてzsh
)いくつかの実装を見つけることができます。たとえば、最近のDebianシステムでは$PATH
。
busybox
コマンドがもう1つありますwhich
。
一つは、GNU
which
おそらく最も豪華なものです。 cshスクリプトの機能をwhich
別のシェルに拡張しようとします。エイリアスと機能が何であるかを知ることで、より良い回答を提供できます(一部のLinuxディストリビューションでは、これにグローバルエイリアスが設定されていると思いますbash
)。
zsh
いくつかあります。オペレーター実行可能ファイルのパスに展開されます。=
ファイル名拡張子演算子と:c
履歴拡張修飾子(ここでは次に適用されます)パラメータ拡張):
$ print -r -- =ls
/bin/ls
$ cmd=ls; print -r -- $cmd:c
/bin/ls
zsh
、zsh/parameters
コマンドハッシュテーブルは、モジュールのcommands
連想配列としても使用されます。
$ print -r -- $commands[ls]
/bin/ls
このユーティリティ(Unix V8 BourneシェルまたはPlan 9 /のユーティリティをwhatis
除く)は、ドキュメント(greps Whatisデータベース、つまりマニュアルページの概要)にのみ使用されるため、実際には関係ありません。rc
es
whereis
3BSD
実行可能ファイル、マニュアルページ、ソースコードを同時に見つけるために使用されるのではなく、現在の環境に基づいていないで、まるで作成されたかのようにwhich
同時に追加されます。繰り返しますが、これは他の要件を満たしています。C
csh
標準の点では、POSIXはcommand -v
and-V
コマンド(POSIX.2008までオプション)を指定します。 UNIX指定type
コマンド(オプションなし)それはすべてです(where
、、、which
はwhence
どの標準でも指定されていません)。
一部のバージョンまではtype
、command -v
Linux Standard Baseの仕様ではオプションでした。これは、たとえば、いくつかの以前のバージョンposh
(両方に基づいているにもかかわらずpdksh
)がどちらもない理由を説明します。command -v
一部のBourneシェル実装にも追加されました(例:Solaris)。
今日の状態
現状はtype
Bourneのようなすべてのシェルに共通です。 (@jarnoが指摘したように、以下の説明の「POSIXモードではないとき」またはAlmquistの一部の子孫のcommand -v
警告/エラーに注意してください。シェル)。使用したい唯一のシェルです(そこにはシェルがなく、組み込まれているからです)。bash
tcsh
which
type
which
tcsh
シェルの外側のシェルでは、シェルzsh
起動which
ファイルの1つまたは一部に同じ名前のエイリアスまたは関数がなく、それに対して定義されたエイリアスまたは関数がない限り、~/.cshrc
これは~/.bashrc
ユーザーに通知することも、そうでない場合もあります。間違ったことを教えてください。$PATH
~/.cshrc
特定の名前のすべてのコマンドを知りたい場合は、移植可能なものはありません。where
intcsh
または inzsh
または in ksh93 およびその他のシェルを使用でき、それらを組み合わせることができます。type -a
bash
zsh
whence -a
type
which -a
提案
実行可能ファイルのパス名を取得します。
スクリプトから実行可能ファイルのパス名を取得するには、いくつかの考慮事項があります。
ls=$(command -v ls)
標準的なアプローチになります。
しかし、いくつかの問題があります。
- 実行ファイルを実行しないと、そのパスを知ることはできません。すべて
type
、、、 ...経験的which
なcommand -v
方法を使用してパスを見つけます。コンポーネントを繰り返して、$PATH
実行権限を持つディレクトリではなく最初のファイルを見つけます。ただし、シェルによっては、多くのコマンド(Bourne、AT&T ksh、zsh、ash...)は、システムコールがエラーを返さない$PATH
まで順番に実行されます。execve
たとえば、含まれていて$PATH
実行/foo:/bar
したい場合はls
最初に実行を試み、/foo/ls
それ以外の場合は失敗します/bar/ls
。/foo/ls
実行権限がないため、実行は失敗する可能性がありますが、有効な実行ファイルではないなど、さまざまな理由で実行が失敗する可能性があります。実行権限があるかどうかcommand -v ls
を報告しますが、/foo/ls
有効な実行ファイルではない場合は、/foo/ls
実行がls
実際に実行される可能性があります。/bar/ls
/foo/ls
foo
組み込み関数、関数、またはエイリアスかどうかを返しcommand -v foo
ますfoo
。またはash
などの一部のシェルでは、pdksh
空の文字列が含まれ、現在のディレクトリに実行可能ファイルが含まれている場合にzsh
返されることがあります。場合によっては、これを考慮する必要があります。組み込み関数のリストは、シェルの実装(時にはbusyboxの組み込み関数)によって異なります。たとえば、環境で関数を取得できることを覚えておいてください。foo
$PATH
foo
mount
sh
bash
$PATH
相対パスコンポーネントが含まれている場合(通常.
または両方の現在のディレクトリを参照しますが、何でもできる空の文字列)、シェルによっては絶対パスがcommand -v cmd
出力されないことがあります。したがって、走行中に得られた経路は、command -v
他の場所に到達した後、もはや有効ではありません。cd
- エピソード:ksh93シェルを使用している場合
/opt/ast/bin
(正確なパスはシステムによって異なる可能性があると思いますが)、$PATH
ksh93は追加の組み込み機能(chmod
、、、cmp
...cat
)を提供しますが、そのパスが存在しない場合command -v chmod
でも/opt/ast/bin/chmod
存在しないものを返しますします。
コマンドが存在することを確認する
特定のコマンドが標準として存在することを確認するには、次のようにします。
if command -v given-command > /dev/null 2>&1; then
echo given-command is available
else
echo given-command is not available
fi
人々が使いたい場所which
(t)csh
csh
と ではtcsh
選択の余地は多くありません。ではこれが内蔵されているtcsh
ので良いです。which
これはcsh
システムwhich
コマンドであり、場合によっては目的の操作を実行できない場合があります。
特定のシェルでのみコマンドを検索する
これを使用するのが合理的である可能性がある状況は、シェルスクリプトで潜在的なシェル組み込み機能や関数を無視してコマンドのパスをwhich
知りたい場合ですbash
。csh
つまり、(例:または)、(例:、、)、(、)、またはシステムで使用でき、スクリプトではなく組み込み関数(例:または)です。tcsh
dash
Bourne
whence -p
ksh
zsh
command -ev
yash
whatis -p
rc
akanga
which
tcsh
zsh
which
csh
これらの条件が満たされると、以下が実行される。
echo=$(which echo)
echo
シェルが組み込み/エイリアス/関数であるかどうかに$PATH
かかわらず(極端な場合を除く)最初の項目へのパスを提供します。echo
他のシェルでは、以下を好みます。
- 扱いにくい:
echo==echo
またはecho=$commands[echo]
またはecho=${${:-echo}:c}
- 変化の多く、扱いにくい:
echo=$(whence -p echo)
- ヤッシュ:
echo=$(command -ev echo)
- RC、アカンガ:(
echo=`whatis -p echo`
空白のあるパスを参照してください) - 魚:
set echo (type -fp echo)
やりたいことがあれば走るこのecho
コマンドを使用すると、パスをインポートすることなく次のようにできます。
env echo this is not echoed by the builtin echo
tcsh
たとえば、組み込み関数の使用を防ぐには、を使用します。which
set Echo = "`env which echo`"
本当に外部コマンドが必要なとき
使用したい別の状況which
は実際には必要外部コマンド。 POSIXでは、すべてのシェル組み込みコマンド(たとえば)を外部コマンドとしても使用できるはずですが、残念ながら多くのシステムではcommand
そうではありません。たとえば、このコマンドはLinuxベースのオペレーティングシステムではほとんど見つかりませんが、ほとんどcommand
のオペレーティングシステムでは使用できます(オペレーティングシステムごとにオプションと動作が異なります)。command
which
外部コマンドが必要な状況は、POSIXシェルを呼び出さずにコマンドを実行したい場合です。
system("some command line")
Cまたはさまざまな言語、...関数はpopen()
シェルを呼び出してコマンドラインを解析するので、system("command -v my-cmd")
その中で作業します。 1つの例外は、perl
シェルにシェル特殊文字(スペースを除く)が表示されない場合、シェルが最適化されることです。これはバックティック演算子でも機能します。
$ perl -le 'print system "command -v emacs"'
-1
$ perl -le 'print system ":;command -v emacs"'
/usr/bin/emacs
0
$ perl -e 'print `command -v emacs`'
$ perl -e 'print `:;command -v emacs`'
/usr/bin/emacs
:;
上記を追加すると、perl
シェルが強制的に呼び出されます。を使用すると、which
このトリックを使用する必要はありません。
答え2
人々がそれを使いたくない理由はwhich
すでに説明されていますが、実際に失敗したシステムのいくつかの例は次のとおりですwhich
。
Bourneのようなシェルはwhich
出力と出力を比較しますtype
(type
シェルの組み込みとしてコマンドを呼び出す方法を知らせるシェルであるため、これは真でなければなりません)。
多くの場合、コーナーしかし、覚えておいてくださいwhich
/type
しばしば極端な場合に使用されます(予期しない動作に対する答えを見つけるために、例:このコマンドはなぜこのように機能し、どのコマンドを呼び出すのですか?)。
ほとんどのシステム、ほとんどのBourne同様のシェル:機能
最も明確なケースは関数です。
$ type ls
ls is a function
ls ()
{
[ -t 1 ] && set -- -F "$@";
command ls "$@"
}
$ which ls
/bin/ls
その理由は、which
実行ファイルと時にはエイリアスに関する情報だけが報告されるからです(常にそうではありませんが)。あなたのシェル)、関数ではありません。
GNUのマニュアルページには、関数の報告に使用する方法の壊れた(引用符を忘れたため$@
)例がありますが、エイリアスと同様にシェルパーサーを実装していないため、だまされやすいです。
$ which() { (alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot "$@";}
$ f() { echo $'\n}\ng ()\n{ echo bar;\n}\n' >> ~/foo; }
$ type f
f is a function
f ()
{
echo '
}
g ()
{ echo bar;
}
' >> ~/foo
}
$ type g
bash: type: g: not found
$ which f
f ()
{
echo '
}
$ which g
g ()
{ echo bar;
}
ほとんどのシステム、ほとんどのBourne同様のシェル:組み込み
別の明らかなケースは、組み込みコマンドまたはキーワードです。which
外部コマンドは、シェルに組み込まれているものが何であるかを知る方法がないためです(一部のシェルは組み込みの組み込みをzsh
動的にロードできます)bash
。ksh
$ type echo . time
echo is a shell builtin
. is a shell builtin
time is a shell keyword
$ which echo . time
/bin/echo
which: no . in (/bin:/usr/bin)
/usr/bin/time
zsh
(これは内蔵された場所には適用されません)which
Solaris 10、AIX 7.1、HP/UX 11i、Tru64 5.1など:
$ csh
% which ls
ls: aliased to ls -F
% unalias ls
% which ls
ls: aliased to ls -F
% ksh
$ which ls
ls: aliased to ls -F
$ type ls
ls is a tracked alias for /usr/bin/ls
これは、ほとんどの商用Unices which
(3BSDの元の実装と同じ)からのcsh
読み取りであるためです~/.cshrc
。現在定義しているエイリアスと実際に使用しているシェルに関係なく、レポートするエイリアスはそこに定義されています。そうですね。
HP/UX または Tru64 の場合:
% echo 'setenv PATH /bin:/usr/bin' >> ~/.cshrc
% setenv PATH ~/bin:/bin:/usr/bin
% ln -s /bin/ls ~/bin/
% which ls
/bin/ls
$path
(SolarisおよびAIXバージョンでは、読み込み前に保存~/.cshrc
し、コマンドを見つける前に復元してこの問題を解決しました。)
$ type 'a b'
a b is /home/stephane/bin/a b
$ which 'a b'
no a in /usr/sbin /usr/bin
no b in /usr/sbin /usr/bin
または:
$ d="$HOME/my bin"
$ mkdir "$d"; PATH=$PATH:$d
$ ln -s /bin/ls "$d/myls"
$ type myls
myls is /home/stephane/my bin/myls
$ which myls
no myls in /usr/sbin /usr/bin /home/stephane/my bin
(もちろん、csh
スクリプトとしてスペースを含む引数を処理すると期待することはできません...)
CentOS 6.4、バッシュ
$ type which
which is aliased to `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
$ alias foo=': "|test|"'
$ which foo
alias foo=': "|test|"'
/usr/bin/test
$ alias $'foo=\nalias bar='
$ unalias bar
-bash: unalias: bar: not found
$ which bar
alias bar='
このシステムでは、GNUコマンドをラップするためにシステム全体にエイリアスが定義されていますwhich
。
偽の出力はsの出力を読みwhich
ましたが、正しく解析する方法がわからず、ヒューリスティック(1行に1つのエイリアス、、、...の後に最初に見つかったコマンドを見つける)を使用するためです。bash
alias
|
;
&
CentOSの最も悪いことは、zsh
完全に良いwhich
組み込みコマンドがありますが、CentOSはそれを機能しないGNUエイリアスに置き換えてそれを中断させることですwhich
。
Debian 7.0、ksh93:
(複数のシェルを持つほとんどのシステムに適用可能ですが)
$ unset PATH
$ which which
/usr/local/bin/which
$ type which
which is a tracked alias for /bin/which
Debianではスクリプト/bin/which
です/bin/sh
。私が知る限りsh
、それはそうですが、dash
そんなときも同じですbash
。
設定を解除してもルックアップはPATH
無効になりませんPATH
。これはシステムのデフォルトパス残念ながら、Debianでは誰も同意しません(dash
そしてbash
has /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
、zsh
has /bin:/usr/bin:/usr/ucb:/usr/local/bin
、ksh93
has /bin:/usr/bin
、mksh
has /usr/bin:/bin
($(getconf PATH)
)、execvp()
(like env
)has :/bin:/usr/bin
(はい、最初に現在のディレクトリを見てください))。
そのため、上記の場合とは異なるデフォルト値をwhich
使用しているため、エラーが発生します。dash
PATH
ksh93
GNUはより良いサービスを提供しておらず、which
次のように報告します。
which: no which in ((null))
/usr/local/bin/which
akanga
(興味深いことに、私のシステムには実際にスクリプトに付属するスクリプトがありますakanga
(rc
デフォルトはシェル派生ですPATH
)/usr/ucb:/usr/bin:/bin:.
)
bash、すべてのシステム:
唯一の人Chrisは彼の答えで言及しました。:
$ PATH=$HOME/bin:/bin
$ ls /dev/null
/dev/null
$ cp /bin/ls bin
$ type ls
ls is hashed (/bin/ls)
$ command -v ls
/bin/ls
$ which ls
/home/chazelas/bin/ls
また、hash
手動で呼び出した後:
$ type -a which
which is /usr/local/bin/which
which is /usr/bin/which
which is /bin/which
$ hash -p /bin/which which
$ which which
/usr/local/bin/which
$ type which
which is hashed (/bin/which)
which
今度は失敗する部分は次のとおりですtype
。
$ mkdir a b
$ echo '#!/bin/echo' > a/foo
$ echo '#!/' > b/foo
$ chmod +x a/foo b/foo
$ PATH=b:a:$PATH
$ which foo
b/foo
$ type foo
foo is b/foo
今、いくつかのシェルを使用してください。
$ foo
bash: ./b/foo: /: bad interpreter: Permission denied
他の人:
$ foo
a/foo
実行できないという事実を事前に知ることもできませwhich
んtype
。b/foo
一部のシェル(たとえば、bash
またはksh
)は、呼び出されたときyash
にfoo
実際に実行しようb/foo
とし、エラーを報告しますが、他のシェル(たとえばzsh
、、、、、、、、など)は、システムコールが失敗した場合に実行されます。ash
csh
Bourne
tcsh
a/foo
execve()
b/foo
答え3
Stephaneが言及していないことの1つは、(私のクイックビューでは)which
シェルのパスハッシュテーブルを知らないことです。その結果、実際の実行結果を示さない結果が返され、デバッグに役に立たなくなります。
答え4
(この質問には「移植性」というタグが付いているため、「対話型の使用」や「使用しているシステムにのみ興味があります」など、質問に対するさまざまな解釈は除外されます。シェルスクリプトでこれを行うべきではないのはなぜですか?)
Stéphaneはオプションの徹底的な分析を提供し、それぞれのオプションが良いか悪いかについての理由を提示します。どんな理由もwhich
常に間違った答えではありません。代わりに小さな影響を与える要因がたくさんあります。そのうちの1つまたはいくつかに耐えることができますが、一緒に服用すると心が変わることがあります。
まだ言及されていないものを使用していない理由の1つは、次which
のような質問があるからです。
which
そもそもなぜ出力が欲しいのですか?
私が意味するのは、時々目標はドロップされた代替品を見つけるのではなく、which
最初に必要とされない方法でコードをリファクタリングすることです。
一般的なパターンは次のとおりです。
CMD=$( which cmd )
# some time later...
$CMD --some --args
ほとんどいつも引用されていないという事実を控えて、$CMD
全体のパターンが壊れたと思います。
CMD=/my/path/to/cmd
依存関係を避けることが目的の場合は、ハードコーディングが重要です$PATH
。
しかし、とにかく検索すると、$PATH
ほとんど常に意味がありません。which
とを完全に削除し、$CMD
以下を作成します。
cmd --some --args
関数やエイリアスにパスを含めるためにパスが必要だと思われる場合は、そのcommand
パスを使用してください。
function cmd {
command cmd --extra-arg "$@"
}
もちろん例外もあり、他に基づいている必要がありますPATH
。この場合は、次のものを使用することをお勧めします。
function cmd {
PATH=$OTHERPATH command cmd "$@"
}
全体的には、避ける「コマンドパスの入手方法」の精神的な近道がありますが、ケースバイケースで考えてみてください。この道は本当に必要ですか?なぜ?
場合によってはwhich
許可されるかもしれませんが、少なくともある程度はより良い解決策があります。他の人のためのチュートリアルを書いている場合は、他のオプションについてもっと考えてみてください。
合理的だと思ってもCMD=$( which cmd ) ; ... $CMD args
避けるべき他の理由があります。which
これは普遍的ではありません
これPOSIXに必要なコマンドのリストを含むcommand
がtype
含まれていませんwhich
。
出力形式が指定されていません。
which
義務があれば見せる説明なしでそのままコマンドを提供するのではなく、コマンドパスを指定してください。ほとんどのバージョンですが。
which foo
以下を出力するのは完全に正当です。
foo might be /opt/foobar/bin/foo (unverified)
;またはfoo is in /bin
;または~foo/bin/foo
(~foo
fooのホームディレクトリを表す)または/proc/1234/root/bin/foo
(プロセス1234終了)
答えは最新ではないかもしれません。
(これは基本的にすべての形式を除外しますが、これにCMD=$( something ) ; ... $CMD ...
限定されませんwhich
。)
特定のコマンド名に対する実行可能ファイルの場所は、さまざまな理由で変更される可能性があります。
時々、あなたは以前の場所を望むかもしれませんし、そうでないかもしれません。
コマンドへのパスが相対的な場合もあります(したがって.
開始ではありません/
)。これは通常セキュリティ上のリスクと見なされるため、まれですが、単に実行すると、cd
プログラムパスが無効になる可能性がある特別な場合にも当てはまります。