「テスト」と/ dev / nullを使用した評価の違いは何ですか?

「テスト」と/ dev / nullを使用した評価の違いは何ですか?

.shホームブレイクにはインストールの有無を確認する他のスクリプトがあることがわかりました。

次の構文を使用してください。

if test ! $(which brew); then

もう一つは、次の構文を使用します。

if ! which brew > /dev/null; then

どちらも終了コードを確認することを知っていますが、which brew両者に異なる違いがあるかどうか疑問に思います。私にとっては、電子がよりきれいで出力をリダイレクトする必要がないので(おそらく間違って)、より効率的だと思います。

which brewまた、出力が送信されているかどうかに関係なく、2番目の項目が実際に実行されるのはなぜですか/dev/null?シェルはどのように機能しますか?

答え1

1つ目は不器用なハッキングで、2つ目はよく犯される間違いです。

これら2つのテストはまったく異なる操作を実行しますが、同じ結果を生成します。

if test ! $(which brew); then

これにより、次のようなテストが行​​われます。出力空だったwhich brew

  • brew検索パスにある場合はwhich brew出力ワードが生成されるため、コマンドは2つの引数pathをtest受け取ります。 2つのパラメータがある場合、2番目のパラメータが空の場合(ここではそうではありません)、最初のパラメータはtrue、そうでない場合はfalseです。!brewtest!
  • 検索パスにない場合、brew出力はwhich brew空であるため、testコマンドは単一の引数を受け取る!のでtesttrueを返します。

パスにbrewスペースが含まれている場合、このコマンドはエラーメッセージと失敗ステータスを生成します。これは引用符なしのコマンド置換の意味です。。ここでは失敗状態が望む結果なので、これをバイパスする方法です。

このコマンドは終了コードをテストしませんwhich brew。終了コードは無視されます。

if ! which brew > /dev/null; then

これはwhich brew成功をテストする簡単な方法です。それは壊れやすいものには依存せず、それ自体に依存しますwhich

which brewどちらの場合も常に呼び出されます。出力にリダイレクトすることが重要な理由は何ですか/dev/null? 「このコマンドの出力を隠す」とは、「このコマンドを実行しない」という意味ではありません。

brew検索パスでコマンドが使用できないことをテストする正しい方法は次のとおりです。

if ! type brew >/dev/null 2>/dev/null; then

バラより「which」を使わないのはなぜですか?それでは何を使うべきですか?

答え2

最初の部分if test ! $(which brew); then ...

  1. 実行するとという実行可能ファイルを検索しますwhich brew。見つかると、名前が標準出力に印刷されます。何も見つからない場合は、エラーメッセージがstderrに出力されます。 (一部のシェルは、組み込み機能とシェル機能、予約語などを報告する組み込み機能を提供します。例)$PATHbrewwhichzsh
  2. $(...)捕まえる標準出力(ただしstderrではありません)...シェルコマンドが何であれ、コマンドラインに引数として入力します。
  3. test ! ...リバース戻りコードが返されましたtest ...test表現を否定する方法です。test ...(このセクションにはオプションはありません。)このセクションが空の文字列でないことを...テストします。...

結果whichという実行可能ファイルを検索するために使用されますbrew。生成されたパスまたは空の文字列をコマンドラインに引数として入れ、引数が空のtest !文字列であることを確認してから0(true)を返します。

第二部if ! which brew > /dev/null; then ...

ここもwhich brew上記と同じです。実行可能ファイルが見つかると、which名前を印刷するだけでなくコードも返します0(true)。何も見つからない場合は、エラーメッセージを印刷して別のコード(エラー)を返します。このコードは、コマンドの前にある!0-> 1、その他->)によって0シェルによって反転されます。それがif心配です。ユーザーは、brew標準出力がwhichリダイレクトされる実際のパスを見たくないからです/dev/null

メモ:

どちらの場合も、stderrはwhichリダイレクトされず、端末に表示される必要があります。

テストしませんでしたが、1つのプロセス/組み込みプロセスしか起動しないので、2番目の形式がより速いと思います。ただし、どちらのコマンドもリダイレクトされます。 2番目のコマンドは/dev/nullwithの出力をキャプチャし、最初はあまり明確に(最初は)明示的にリダイレクトします。おおよその速度を比較できます。which$(...)comp私が使用する機能

whichとのマニュアルページがありますtest。シェルのマニュアルページ(shkshbashzsh)には、リダイレクトとコマンドの置き換えと組み込み(それだけでなく組み込みwhichとしてtest実装される)に関するセクションがあります。

関連情報