実行可能ファイルへのパスを検索するとき、またはUnixシェルにコマンド名を入力するとどうなるかを確認するときは、さまざまなユーティリティがあります( which
、type
、command
、whence
、where
、whereis
、whatis
、hash
など)。
which
は避けるべきだとよく耳にしますが、なぜですか?代わりに何を使用する必要がありますか?
コメント
回答
これがあなたがそれについて知りたくないと思ったことのないすべてです:
要約
取得するにはBourneのようなシェルスクリプトの実行可能ファイルのパス名(いくつかの注意点があります。以下を参照してください):
ls=$(command -v ls)
特定のコマンドが存在するかどうかを確認するには、次の手順に従います。
if command -v given-command > /dev/null 2>&1; then echo given-command is available else echo given-command is not available fi
インタラクティブなボーンのようなシェルのプロンプトで:
type ls
which
コマンドは、Cシェルからの壊れた遺産であり、ボーンのようなシェルにそのままにしておく方がよいでしょう。
ユースケース
そこに「スクリプトの一部としてその情報を検索するか、シェルプロンプトで対話的に検索するかを区別します。
シェルプロンプトでの一般的な使用例は次のとおりです。このコマンドの動作がおかしい、私はmycmd
?それが何であるかをさらに詳しく調べることはできますか?
その場合、実際にコマンドを呼び出さずにコマンドを呼び出したときにシェルが何をするかを知りたいと思います。
シェルスクリプトでは、かなり異なる傾向があります。シェルスクリプトでは、実行するだけでコマンドがどこにあるのか、何であるのかを知りたい理由はありません。一般に、知りたいのは実行可能ファイルのパスです。そのため、実行可能ファイルからより多くの情報を取得できます(それに関連する別のファイルへのパスや、そのパスにある実行可能ファイルのコンテンツから情報を読み取るなど)。
インタラクティブに、システムで使用可能なすべての my-cmd
コマンドについてスクリプトで知りたい場合があります。 p>
利用可能なツールのほとんど(よくあることですが)は、インタラクティブに使用できるように設計されています。
履歴
最初に少し履歴を付けます。
70年代後半までの初期のUnixシェルには、関数やエイリアスがありませんでした。 $PATH
での実行可能ファイルの従来の検索のみ。 csh
は1978年頃にエイリアスを導入しました(ただし、csh
は2BSD
で最初にリリースされました / div>、1979年5月)、およびユーザーがシェルをカスタマイズするための.cshrc
の処理(すべてのシェル、csh
、スクリプトのようにインタラクティブでない場合でも.cshrc
を読み取ります。
Bourneシェルは1979年の初めにUnixV7で最初にリリースされましたが、関数のサポートは大幅に追加されました。後で(SVR2では1984年)、とにかく、rc
ファイルはありませんでした(.profile
は、シェルではなく環境を構成するためのものですそれ自体)。
csh
は、Bourneシェルよりもはるかに人気がありました(ただし、構文はBourneシェルよりもひどく劣っていました) Bourne shell)インタラクティブに使用するためのより便利で優れた機能がたくさん追加されていました。
3BSD
(1980)では、 which
cshスクリプトがcsh
ユーザー向けに追加され、実行可能ファイルを識別できるようになりました。これは、最近の多くの商用Unice(Solaris、HP / UX、AIX、Tru64など)。
そのスクリプトはユーザーの~/.cshrc
(すべてのcsh
スクリプトは、csh -f
で呼び出されない限り実行されます)、エイリアスのリストで指定されたコマンド名を検索し、 $path
(csh
が$PATH
に基づいて維持する配列)
ここに行きます:which
は、当時最も人気のあったシェルで最初に登場しました(そして、csh
は、半ばまでまだ人気がありました- 90年代)、これが本に記載され、今でも広く使用されている主な理由です。
csh
ユーザーの場合でも、which
cshスクリプトは必ずしもあなたに与えるとは限りません正しい情報。 ~/.cshrc
で定義されたエイリアスを取得します。後でプロンプトで定義したエイリアスや、たとえばsource
別の
ファイル、および(それは良い考えではありませんが)、PATH
は~/.cshrc
。
Bourneシェルからwhich
コマンドを実行すると、~/.cshrc
で定義されているエイリアスが検索されますが、 csh
を使用していないために持っていない場合でも、おそらく正しい答えが得られます。
同様の機能はに追加されていません。 type
組み込みコマンドを使用したSVR2の1984年までのBourneシェル。 (外部スクリプトではなく)組み込みであるという事実は、シェルの内部にアクセスできるため、 適切な情報を(ある程度)提供できることを意味します。
最初のtype
コマンドには、which
スクリプトと同様の問題があり、次の場合に失敗の終了ステータスが返されませんでした。コマンドが見つかりませんでした。また、実行可能ファイルの場合、which
とは異なり、iv id = “ではなくls is /bin/ls
のように出力されます。 1ef2ca896a “>
により、スクリプトでの使用が容易になりませんでした。
Unixバージョン8″(実際にはリリースされていません)Bourneシェルにはtype
ビルトインの名前がwhatis
に変更されました。Plan9(かつてはUnixの後継であった)シェルrc
(およびそのakanga
やes
)などの派生物にもwhatis
があります。
Kornシェル(そのサブセットのPOSIX sh
の定義は)に基づいており、80年代半ばに開発されましたが、1988年以前は広く利用できませんでしたが、csh
機能の多くが追加されました( Bourneシェルの上にあるラインエディタ、エイリアス…)。独自のwhence
ビルトイン(type
に加えて)を追加し、いくつかのオプションを取りました(-v
type
のような詳細な出力を提供し、-p
は実行可能ファイルのみを検索します(エイリアス/関数ではありません…)) 。
AT & Tとバークレーの間の著作権問題に関する混乱と一致して、いくつかのフリーソフトウェアシェルの実装が行われました。 80年代後半から90年代前半にかけて。すべてのAlmquistシェル(ash
、BSDのBourneシェルの代わりになります)、ksh
(pdksh
)、bash
(FSF主催)、zsh
は1989年から1991.
Ashは、Bourneシェルの代わりになることを意図していましたが、ずっと後になるまでtype
が組み込まれていませんでした(NetBSD1.3およびFreeBSD2.3)。 )、ただしhash -v
がありました。OSF/ 1 /bin/sh
にはtype
が組み込まれていました。 OSF / 1v3.xまでは0を返しました。bash
はwhence
を追加しませんでしたが、iv id = “bcb57bbe4a”を追加しましたパスを出力するためのtype
の> オプション(type -p
はwhence -p
)および-a
を使用して、一致するコマンドをすべて報告します。 tcsh
はwhich
を組み込み、where
コマンドを追加してbash
” s type -a
。zsh
にはすべてがあります。
fish
シェル(2005)には、関数として実装されたtype
コマンドがあります。
which
cshスクリプトはNetBSDから削除され(tcshに組み込まれていて、他のシェルではあまり使用されていないため)、機能がwhereis
に追加されました(which
、whereis
はwhich
のように動作しますが、)。OpenBSDとFreeBSDでは、which
も$PATH
でのみコマンドを検索するCで記述されたものに変更されました。 。
実装
which
coの実装は数十あります。構文と動作が異なるさまざまなユニスのmmand。
Linuxの場合(tcsh
とzsh
の組み込みのもののほかに)いくつかの実装があります。たとえば、最近のDebianシステムでは、「$PATH
でコマンドを検索する単純なPOSIXシェルスクリプトです。
busybox
にはwhich
コマンドもあります。
GNU
which
はおそらく最も贅沢なものです。which
cshスクリプトが行ったことを他のシェルに拡張しようとします。エイリアスと関数が何であるかを教えて、与えることができます。あなたはより良い答えです(そして、いくつかのLinuxディストリビューションは、それを行うために、その周りにいくつかのグローバルエイリアスを設定していると思います)。
zsh
には、実行可能ファイルのパスに展開する演算子がいくつかあります。=
ファイル名展開演算子と div id = “38f34b9ab5”> 履歴拡張修飾子(ここではパラメーター拡張に適用):
$ print -r -- =ls /bin/ls $ cmd=ls; print -r -- $cmd:c /bin/ls
zsh
、モジュールは、コマンドハッシュテーブルをcommands
連想配列として作成します:
$ print -r -- $commands[ls] /bin/ls
whatis
ユーティリティ(Unix V8BourneシェルまたはPlan9 rc
/ es
)は、ドキュメント専用であるため、実際には関連していません(whatisデータベース、つまりmanページの概要を取得します)。
whereis
も関連していました。 C
で記述されていても、which
と同時に3BSD
に追加されました。 csh
は、実行可能ファイル、マニュアルページ、およびソースを同時に検索するために使用されますが、現在の環境に基づくものではありません。繰り返しになりますが、これは別のニーズに応えます。
現在、標準的な面では、POSIXはcommand -v
と-V
コマンド(POSIX.2008まではオプションでした)。 UNIXは、type
コマンドを指定します(オプションなし)。以上です(where
、which
、whence
はどの規格でも指定されていません) 。
一部のバージョンまで、type
とcommand -v
は、Linux StandardBase仕様ではオプションでした。たとえば、posh
のいくつかの古いバージョン(両方を持っていたpdksh
に基づく)にはどちらもありませんでした。 command -v
は、一部のBourneシェル実装(Solarisなど)にも追加されました。
今日の状況
今日の状況は、type
とcommand -v
がすべてに遍在していることです。ボーンのようなシェル(ただし、@ jarnoで指摘されているように、POSIXモードでない場合、またはコメントで以下のAlmquistシェルの子孫である場合は、bash
の警告/バグに注意してください)。 tcsh
は、which
を使用する唯一のシェルです(type
があり、which
が組み込まれています。
tcsh
と、which
は、
、~/.bashrc
、または任意のシェル起動ファイルで、ividに
$PATH
を定義しない= “c92e1ab12d”> 。エイリアスまたは関数が定義されている場合、それについて通知する場合としない場合があります。または、間違ったことを通知する場合があります。
知りたい場合与えられた名前のすべてのコマンドについては、移植性のあるものは何もありません。 tcsh
またはzsh
、iv id = “9a534a3bbe”で、where
を使用します。 > bash
またはzsh
、whence -a
のksh93およびその他のシェル、type
をwhich -a
と組み合わせて使用できます。
推奨事項
実行可能ファイルへのパス名の取得
スクリプトで実行可能ファイルのパス名を取得するには、いくつかの注意点があります。
ls=$(command -v ls)
これを行うための標準的な方法です。
ただし、いくつかの問題があります。
- 実行可能ファイルを実行せずにパスを知ることはできません。すべて
type
、which
、command -v
…すべてヒューリスティックを使用してパスを見つけます。$PATH
コンポーネントをループして、実行権限を持つ最初の非ディレクトリファイルを見つけます。ただし、depeシェルを見つけると、コマンドの実行に関しては、それらの多く(Bourne、AT & T ksh、zsh、ash …)は、次の順序で実行します。 は、execve
システムコールがエラーで返されないまで続きます。たとえば、$PATH
に/foo:/bar
が含まれていて、ls
を実行する場合、最初に試行されます。/foo/ls
を実行するか、失敗した場合は/bar/ls
を実行します。/foo/ls
の実行は、実行権限がないために失敗する可能性がありますが、有効な実行可能ファイルではないなど、他の多くの理由もあります。/foo/ls
の実行権限があるが、iv idを実行している場合、command -v ls
は/foo/ls
を報告します/foo/ls
が有効な実行可能ファイルでない場合、= “d15a078f48”> は実際に/bar/ls
を実行する可能性があります。 -
foo
が組み込み、関数、またはエイリアスの場合、command -v foo
はfoo
を返します。ash
、pdksh
、zsh
などの一部のシェルでは、$PATH
に空の文字列が含まれていて、現在のディレクトリに実行可能なfoo
ファイルがある場合。これを考慮する必要がある場合があります。たとえば、組み込みのリストはシェルの実装によって異なることに注意してください(たとえば、mount
はbusybox用に組み込まれている場合がありますsh
)、たとえばbash
は環境から関数を取得できます。 - if
$PATH
には、シェルに応じて、相対パスコンポーネント(通常は.
または空の文字列(どちらも現在のディレクトリを参照しますが、何でもかまいません))が含まれます。command -v cmd
は絶対パスを出力しない可能性があるため、は、他の場所でcd
を実行すると、無効になります。 - 事例:(正確なパスはシステムによって異なる可能性があります)
$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
(
またはzsh
)、command -ev
(yash
など)、whatis -p
(rc
、akanga
)または組み込みのwhich
(tcsh
またはzsh
など)which
が存在するシステム利用可能であり、csh
スクリプト。
これらの条件が満たされている場合:
echo=$(which echo)
最初のividのパスが表示されますecho
がシェルであるかどうかに関係なく、$PATH
の= “46435c0fe2”> (コーナーの場合を除く)組み込み/エイリアス/関数かどうか。
他のシェルでは、次のようにします。
- zsh :
echo==echo
またはecho=$commands[echo]
またはecho=${${:-echo}:c}
- ksh 、 zsh :
echo=$(whence -p echo)
- yash :
echo=$(command -ev echo)
- rc 、 akanga :
echo=`whatis -p echo`
(スペースのあるパスに注意) - 魚:
set echo (type -fp echo)
実行するのが実行だけの場合は注意してください/ em>そのecho
コマンド、パスを取得する必要はありません。次のようにするだけです。
env echo this is not echoed by the builtin echo
たとえば、tcsh
を使用して、組み込みのwhich
が使用されないようにするには:
set Echo = "`env which echo`"
外部コマンドが必要な場合
which
を使用するもう1つのケースは、実際に必要な場合です。 外部コマンド。 POSIXでは、すべてのシェルビルトイン(command
など)を外部コマンドとしても使用できる必要がありますが、残念ながら、command
には当てはまりません。多くのシステムで。たとえば、Linuxベースのオペレーティングシステムでcommand
コマンドを見つけることはめったにありませんが、ほとんどのシステムにはwhich
コマンド(ただし、オプションと動作が異なります)。
POSIXシェルを呼び出さずにコマンドを実行する場合は、外部コマンドが必要になる可能性があります。
system("some command line")
、popen()
… Cまたはさまざまな言語の関数は、シェルを呼び出してそのコマンドラインを解析するため、system("command -v my-cmd")
はそれらの中で動作します。例外は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
を使用すると、そのトリックを使用する必要がなくなります。
コメント
- @ Joe、
which
は、多くの商用ユニスのcsh
スクリプトです。その理由は歴史的であり、’が私が歴史を与えた理由であり、人々はそれがどこから来たのか、なぜ人々がそれを使用することに慣れたのか、そしてなぜ実際にそこにあるのかを理解しています’それを使用すべき理由はありません。そして、はい、一部の人々は(t)cshを使用します。まだ誰もがLinuxを使用しているわけではありません - この投稿を読んだ後、答えのコンテキストはたくさん見つかりましたが、答え自体は見つかりませんでした。この投稿のどこに、
which
9b39b47e6e “> を使用しない理由が実際に記載されています。 実行する、which
の履歴、which
の実装、関連タスクを実行するその他のコマンド、または実際に使用する理由which
?他のコマンドが優れているのはなぜですか?which
との違いは何ですか?彼らはどのようにしてその落とし穴を回避しますか?この回答は、実際には、which
の問題よりも代替案の問題に多くの単語を費やしています。 -
command
について説明します。 POSIXによる。 - @St é faneChazelas
touch /usr/bin/mytestfile
で新しいファイルを作成し、その後command -v mytestfile
、パスを提供します(which mytestfile
は提供しません)。 - @jarno、そうそう、あなた’正解です。
bash
は、実行可能ファイルが見つからない場合、実行不可能なファイルに落ち着きます。’実行可能ファイルが見つからないため、’ s ” OK “(ただし、実際にはcommand -v
/type
はエラーを返します)’は、mytestfile
ですが、dash
の動作はバグがあり、’実行不可能なcmd
実行可能ファイルの前にcommand -v
は実行可能ファイルを返しますが、cmd
を実行すると実行可能ファイルが実行されます(間違っています) 1つもハッシュされます)。 FreeBSDsh
(これもash
に基づく)にも同じバグがあります。 zsh、yash、ksh、mksh、bash asshはOKです。
回答
理由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
は実行可能ファイルについてのみ報告し、場合によってはエイリアス(シェルのエイリアスであるとは限りません)についてのみ報告し、関数については報告しないためです。
manページの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
は外部コマンドであるため、シェルにどのビルトインがあるか(および、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、Tru645。 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
これは、ほとんどの商用ユニスではwhich
(元の実装と同様)であるためです。 3BSD)は、~/.cshrc
を読み取るcsh
スクリプトです。レポートされるエイリアスは、現在定義しているエイリアスや実際に使用しているシェルに関係なく、そこで定義されているエイリアスです。
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
(SolarisおよびAIXバージョンでは、~/.cshrc
divを読み取る前に$path
を保存することで、この問題を修正しています。 >コマンドを検索する前に復元します)
$ 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、bash
$ 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
コマンドをラップするシステム全体で定義されたエイリアスがあります。
偽の出力は、which
がbash
のalias
しかし、それを適切に解析する方法がわからず、ヒューリスティックを使用します(1行に1つのエイリアス、|
、、&
…)
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
ルックアップを無効にすることではなく、システムのデフォルトのPATH は残念ながらDebianで、誰も同意しません(dash
とbash
には/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
、zsh
には/bin:/usr/bin:/usr/ucb:/usr/local/bin
、ksh93
には/bin:/usr/bin
、mksh
には/usr/bin:/bin
($(getconf PATH)
)、execvp()
(env
のように)には:/bin:/usr/bin
があります(はい、最初に現在のディレクトリを調べます!)) 。
which
は、dash
のデフォルトのividを使用しているため、上記で間違っているのはそのためです。 ksh93
“s
とは異なる=” ac187d6c45 “>
報告するGNUwhich
の方が優れています:
which: no which in ((null))
(興味深いことに、確かには、実際にはakanga
(rc
デフォルトのPATH
が/usr/ucb:/usr/bin:/bin:.
))
bash、任意のシステムであるシェル派生物:
$ 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
がbできないことを事前に知ることができますe実行されました。 iv id = “488253cbe9を呼び出す場合、bash
、ksh
、yash
などの一部のシェル”> は実際にb/foo
を実行してエラーを報告しようとしますが、他の(zsh
、、csh
、Bourne
、tcsh
)が実行されますexecve()システムコールがb/foo
で失敗した場合のdivid = “4234cc97bf”> 。
コメント
-
mksh
は実際にはデフォルトの$PATH
とは異なるものを使用しています。 、オペレーティングシステムのコンパイル時定数_PATH_DEFPATH
が使用され(最も一般的にはBSDで)、次にconfstr(_CS_PATH, …)
が使用されます(POSIX)、両方が存在しないか失敗した場合は、/bin:/usr/bin:/sbin:/usr/sbin
が使用されます。 - 最初の例では、
ls
はそれが使用している関数ですg PATHからls
。また、which
は、/usr/bin/ls
または/usr/local/bin/ls
のどちらが使用されているかを示します。 ‘ “どの” ….を使用しないのかわかりません。 - @rudimeier、その
which ls
は、ls
に関係なく、/bin/ls
を提供します。 div>関数は、/bin/ls
または/opt/gnu/bin/ls
またはdir
を呼び出すか、まったく呼び出しません。 IOW、which
(実装、IMMV)は、無関係なものを提供しています - @St é phaneChazelas。ダメダメダメ。
ls
が関数であることを知っています。ls
関数がPATH
divからls
を呼び出していることを知っています >。これで、which
がファイルの場所を教えてくれます。単一のユースケースのみが表示されます:”このコマンドでシェルは何をしますか。”このユースケースの場合which
は間違っています、正しいです。ただし、(GNU)which
が正確に正しい場合もあります。 - @rudimeter、
which
の実装。 ‘がエイリアスであると言う人もいます(エイリアスが構成されている場合、または自宅に~/.cshrc
がある場合そのようなエイリアス)、いくつかはあなたにパスを与えますが、いくつかの条件下では間違ったものです。sh -c 'command -v ls'
ですが、完全ではありませんが、そのさまざまな要件に対する正しい答えが得られる可能性が高くなります(標準でもあります)。
回答
(私のクイックスキムから)ステファンが言及しなかったと思われることの1つは、which
がシェルのパスハッシュテーブルについてはわかりません。これには、実際に実行されているものを表していない結果が返される可能性があり、デバッグに効果がないという効果があります。
回答
which
での根拠のないバッシングは誰にとっても役に立たないため、疑いを持たないユーザーにこの質問が推奨される場合、私は通常、うんざりします。
はうまく機能し、Unixのモトに従って、いくつかのタスクに正しい答えを提供します。 1つのことを実行し、うまく実行する、なぜwhich
は禁止されますか?
では、どちらがうまく機能し、特定の仕事をうまく行うかという問題がありますか?
1つは、Debianの/ bin / whichにある外部ユーティリティです。は、パスに指定された名前の実行可能ファイルを一覧表示することだけを目的としたシェルスクリプトです。 which
は意図した目標を正しく実行していると思います。エイリアス、関数、シェルからの何もロードせず、PATHに指定された名前の最初の(またはすべての)実行可能ファイルをリストするだけです。 指定された名前と同じ名前のファイルを見つけたことを意味するは、ユーザーが彼女(彼)によって理解する必要があるものです。自己。
はい、他のwhich
実装には特定の問題がある可能性があります(通常はあります)。
回答
避けるべきことをよく耳にします。どうして?代わりに何を使用すればよいですか?
聞いたことがありません。具体的な例を挙げてください。 which
の出所については、Linuxディストリビューションとインストールされているソフトウェアパッケージについて心配します!
SLES 11.4 x86-64
tcshバージョン6.18.01:
> which which which: shell built-in command.
bashバージョン3.2-147:
> which which /usr/bin/which > which -v GNU which v2.19, Copyright (C) 1999 - 2008 Carlo Wood. GNU which comes with ABSOLUTELY NO WARRANTY; This program is free software; your freedom to use, change and distribute this program is protected by the GPL.
which
は util-linux Linuxオペレーティングシステムの一部として使用するためにLinuxカーネル組織によって配布される標準パッケージ。また、これらの他のファイルも提供します
/bin/dmesg /bin/findmnt /bin/logger /bin/lsblk /bin/more /bin/mount /bin/umount /sbin/adjtimex /sbin/agetty /sbin/blkid /sbin/blockdev /sbin/cfdisk /sbin/chcpu /sbin/ctrlaltdel /sbin/elvtune /sbin/fdisk /sbin/findfs /sbin/fsck /sbin/fsck.cramfs /sbin/fsck.minix /sbin/fsfreeze /sbin/fstrim /sbin/hwclock /sbin/losetup /sbin/mkfs /sbin/mkfs.bfs /sbin/mkfs.cramfs /sbin/mkfs.minix /sbin/mkswap /sbin/nologin /sbin/pivot_root /sbin/raw /sbin/sfdisk /sbin/swaplabel /sbin/swapoff /sbin/swapon /sbin/switch_root /sbin/wipefs /usr/bin/cal /usr/bin/chrp-addnote /usr/bin/chrt /usr/bin/col /usr/bin/colcrt /usr/bin/colrm /usr/bin/column /usr/bin/cytune /usr/bin/ddate /usr/bin/fallocate /usr/bin/flock /usr/bin/getopt /usr/bin/hexdump /usr/bin/i386 /usr/bin/ionice /usr/bin/ipcmk /usr/bin/ipcrm /usr/bin/ipcs /usr/bin/isosize /usr/bin/line /usr/bin/linux32 /usr/bin/linux64 /usr/bin/look /usr/bin/lscpu /usr/bin/mcookie /usr/bin/mesg /usr/bin/mkzimage_cmdline /usr/bin/namei /usr/bin/rename /usr/bin/renice /usr/bin/rev /usr/bin/script /usr/bin/scriptreplay /usr/bin/setarch /usr/bin/setsid /usr/bin/setterm /usr/bin/tailf /usr/bin/taskset /usr/bin/time /usr/bin/ul /usr/bin/uname26 /usr/bin/unshare /usr/bin/uuidgen /usr/bin/wall /usr/bin/whereis /usr/bin/which /usr/bin/write /usr/bin/x86_64 /usr/sbin/addpart /usr/sbin/delpart /usr/sbin/fdformat /usr/sbin/flushb /usr/sbin/freeramdisk /usr/sbin/klogconsole /usr/sbin/ldattach /usr/sbin/partx /usr/sbin/rcraw /usr/sbin/readprofile /usr/sbin/rtcwake /usr/sbin/setctsid /usr/sbin/tunelp
私のutil-linux
はバージョン2.19です。リリースノートは、2007年8月28日付けのv2.13までさかのぼって簡単に見つけることができます。これのポイントまたは目標が何であったかはわかりませんが、331回賛成されたその長いものでは確かに答えられませんでした。
コメント
- どのように質問は、それが何を指しているのかについては言及していません。 Linuxは数少ないものの1つにすぎません。
-
which -v
が示すように、’はGNUです(贅沢な1つは他の回答で言及されており、Linuxに固有のものではありません)、AFAIKにwhich
ユーティリティが含まれていなかったutil-linuxではありません。 util-linux 2.19は2011年のもので、GNUは2008年のものです。
which
の使用に反対するほとんどの議論は、インタラクティブなシェルコンテキストを想定していると思います。この質問には/ portabilityというタグが付けられています。このコンテキストでの質問は、”which
の代わりに、$PATH
“。ほとんどの回答と理由which
は、エイリアス、ビルトイン、関数を扱います。これらは、ほとんどの実際のポータブルシェルスクリプトで学術的に関心があります。ローカルで定義されたエイリアスは、シェルスクリプトの実行時に’継承されません(.
でソースを指定しない限り)。csh
(およびwhich
はほとんどの商用でまだcsh
スクリプトですUnices)は、非対話型の場合、~/.cshrc
を読み取ります。そのため、’ ‘ cshスクリプトは通常#! /bin/csh -f
で始まることに気付くでしょう。which
は、エイリアスを提供することを目的しているためではありません。これは、’が(インタラクティブ)csh
のユーザー。 POSIXシェルユーザーはcommand -v
を持っています。(t)csh
でない限り、答えは常にになります。 div>(または、’正しい結果が得られなくても’気にしないでください)、またはcommand -v
。 理由の回答を参照してください。stat $(which ls)
はいくつかの理由で間違っています(、引用符がありません)、which
)の使用法だけではありません。 ‘stat -- "$(command -v ls)"
を使用します。これは、ls
が実際にファイルシステムにあるコマンドであることを前提としています(シェルの組み込みやエイリアスの機能ではありません)。which
が間違ったパス(ls
を入力した場合にシェルが実行するパスではない)を提供したり、定義されたエイリアスを提供したりする可能性があります他のいくつかのシェルの構成では…which
の実装でさえも得られない条件がいくつかあります。ls
は、$PATH
のルックアップによって検出されます(ls
に関係なくシェルで呼び出すことができます)。sh -c 'command -v ls'
またはzsh -c 'rpm -q --whatprovides =ls'
が正しい答えを与える可能性が高くなります。ここでのポイントは、which
はcsh
からの壊れた遺産であるということです。