「/ bin / [」はどのように機能しますか?


50

私はいつもフォルダー/bin[プログラムがあることに驚いています。

これは、次のようなことをしているときに呼び出されるものif [ something ]ですか?

[シェルでプログラムを明示的に呼び出すことにより、対応するを要求し]、閉じ括弧を指定すると、括弧の間に何を挿入しても何もしないようです。

言うまでもなく、プログラムに関するヘルプを得ることについて、通常の方法でうまくいかない、つまりどちらman [[ --help動作します。


11
@IporSircerは [を指しtest、かかわらコマンドではないexpr、それはする必要がありますので、man test
Sergiy Kolodyazhnyy

8
man '['私にとってはうまくいく-あなたが引用するのを忘れた[か、または「作品」の別の定義を持っているかのどちらか。
トビースパイト

3
いくつかの警告:[引数を評価するため、すべての引数の間にスペースが必要です。 [ a=b ]比較ではありません:常にtrue(単一の文字列: "a = b"、これは常にtrueに評価されます)そして、引数の数を4に制限する必要があります(最近の実装ではさらに許可されます。)たとえば、[ "a" = "b" ]4つの引数に制限すると、すでに4つの引数があります: "a" "=" "b"およびテストの不要な終了引数: "]")。さらに必要な場合:次のようなチェーンテスト:if [ "$Var_a" = "foo" ] && [ "$Var_b" = "bar" ] ; then : do something ; fi
オリビエデュラック

1
@OlivierDulac a !自体(エスケープされておらず引用符も付いていない)は置き換えられませんif ! [ ...。使用するすべてのbash拡張に!は、少なくとも他のキャラクターが含まれています
-muru

3
また、[-builtin in bash(および場合によっては他のシェル)もあり、これはの代わりに使用できることに注意してください/bin/[。またtest、多くのシステムでは/bin/[(またはその逆)のシンボリックリンクである-commandがありますが、別のコマンドでは別のコマンドです。
バールドコッペルド

回答:


63

[コマンドの仕事は、テスト式を評価することです。式がtrueに解決される場合は0の終了ステータス(trueを意味する)を返し、そうでない場合は他の何か(falseを意味する)を返します。

何もしないのではなく、結果が終了ステータスで見つかるというだけです。シェルでは$?、Bourneのようなシェルまたは$status他のほとんどのシェル(fish / rc / es / csh / tcsh ...)の最後のコマンドの終了ステータスを確認できます。

$ [ a = a ]
$ echo "$?"
0
$ [ a = b ]
$ echo "$?"
1

などの他の言語perlでは、終了ステータスは、たとえば次の戻り値で返されますsystem()

$ perl -le 'print system("[", "a", "=", "a", "]")'
0

すべての最新のBourne風のシェル(およびfish)には組み込み[コマンドがあることに注意してください。/bin通常、1つは、別のシェルを使用するときenv [ foo = bar ]find . -exec [ -f {} ] \; -printまたはperl上記のコマンドまたは上記のコマンドを実行するときにのみ実行されます

[コマンドもで知られているtest名前。として呼び出されたtest場合、終了]引数は必要ありません。

あなたのシステムにはマニュアルページがないかもしれませんが、[おそらくマニュアルページがありますtest。しかし、再び、それは文書化することに注意してください/bin/[または/bin/test実装を。[シェルのビルトインについて知るには、代わりにシェルのドキュメントを読む必要があります。

そのユーティリティの履歴と[[...]]kshテスト式との違いの詳細については、こちらの他のQ&Aをご覧ください


良い、いつものように。@Bregaladの質問の下に追加したコメントに追加したいですか?または多分余分なもの?そうすれば、答えは「どのように正確に機能するか」についてさらに完全になります(私はあなたがすでに「]」についてより正確な情報を提供したことに注意してください^^)
オリビエデュラック

「すべてのBourne風のシェル(および魚)には組み込みの[コマンド]があります。これは21世紀の実際に当てはまりますが、を使用せずにシェルを使用したことは間違いありません[。それがBourneの変種か、灰のアンティークバージョンかを覚えていません。
ジル 'SO-悪であるのをやめる'

@Gilles Bourneシェルは、Unix System IIIの組み込み[およびtest組み込みとして実装されました。その前に、そこにはなかった[し、test唯一の外部バイナリコマンドでした。
jlliagre

@Gilles、元の灰にはテストが組み込まれていました(exprにマージされました)が、オプションでin-ulm.de/~mascheck/various/ashによると、BSDには2000年頃までテスト組み込み機能がありませんでした。「モダン」を追加しました。
ステファンシャゼラス

なぜ世界でやりたいのですfind . -exec [ f {} ] \; -printか?コマンドがfind . -type f -print同じことをするだろうので、はるかに効率的に...
これが私の本当の名前ではありません

41

私はいつもフォルダー/bin[プログラムがあることに驚いています。

あなたは驚くでしょう。これは、nullユーティリティ(:)を備えたまれなPOSIXコマンドの1つであり、コマンドファイルで許可される文字規則(ポータブルファイル名文字セット)を尊重しません。

私たちが次のようなことをしているとき、それは何と呼ばれていif [ something ]ますか?

正確に、しかしそれなしでも使用できますif

[シェルでプログラムを明示的に呼び出すことにより、対応するを要求し]、閉じ括弧を指定すると、括弧の間に何を挿入しても何もしないようです。

目に見えるものは何もありませんが、実際にはで使用した場合とまったく同じことifを行います。つまり、ブラケット内に何を入れたかに応じて終了ステータスを0(true)またはその他(false)に設定します。(理由により)testコマンドと同じ動作です。唯一の違いは、エンディングを探すこと]です。詳細man testを参照してください。

言うまでもなく、プログラムに関するヘルプを得ることについて、通常の方法でうまくいかない、つまりどちらman [[ --help動作します。

それはオペレーティングシステムに依存します。man [いくつかの主流のGnu / Linuxディストリビューションで間違いなく動作しますが、Solarisでは動作しません。

[ --helpとにかく構文を壊し、endingが欠落しているため、実装に応じて機能する場合と機能しない場合があります]。さらに、/ コマンドのPOSIX標準ではtest[--オプションの終了を含むすべてのオプションが明示的に除外されているため、両方[ --help ]ともtest --help返さtrueれ、設計上でサイレントである必要があります。カッコ内またはカッコ内に配置し、[オプションのように見えるもの(たとえば-f file-n stringなど)はオプションではなくオペランドであることに注意してください。

すべての近代的なボーンスタイルのシェルインタプリタ(のようなbashkshdashおよびzsh数名に)を実装test/の[あなたがそれらを使用する際に参照するための権利マニュアルページは、シェルの1、ないかもしれないので、内部組み込みなどのユーティリティをtest1。

Unix System III(1981)以前は、Bourneシェルはtestユーティリティをビルトインとして実装していなかったため、外部バイナリコマンドの実装のみが利用可能でした。[Unix System IIIまでコマンド(内部または組み込み)がなかったため、たとえばUnixバージョン7では次のように入力する必要がありました。

if test something ; then

の代わりに:

if [ something ] ; then


「男[メインストリームGnu / Linuxディストリビューションで間違いなく動作します]うーん。Centos(確かに6.8まだ)はメインストリームではないことは明らかです:) man test動作しますがman [ 、一方で私のcygwin環境は知っていman [ます!
アダム

1
@Adamはい、そうです、それは私が思ったよりも最近のことです。すべての主流のLinuxディストリビューションを書いたわけではありません。それはOL 7.2(RHEL 7.2)クローンとMint 17.1(Ubuntu 14.04)です。
-jlliagre

man [Manjaro(Arch Linuxベース)では動作しないようです。ヘルプを表示する有効な呼び出しとしてのtestリストのマニュアル[ --helpですが、興味深いことに、それは表示されず、代わりにの]場合と同じように、行方不明について文句を言い--versionます。を追加]しても何も起こりませんman test
ダークホッグ

@Darkhogg /usr/bin/[ --helpまたはを試すことができ/bin/[ --helpます。
jlliagre

1
@jlliagreあなたは完全に正しいです、私は組み込みを使用していました。完全に問題env [ --helpなく/usr/bin/[ --help動作します(ただし、引用/usr/bin/[やzshの苦情が必要です)。
ダークホッグ

10

[実際にはtestコマンドとしてより一般的に知られています。このコマンドの典型的な使用法は、単純に式を評価してその条件を返すことです-trueまたはfalse。これはif-then-else-fiステートメントでよく使用されますが、ifステートメントの外で使用して、シェル&&||演算子を介して他のコマンドを条件付きで実行することもできます。

$ [ -e /etc/passwd  ] && echo "File exists"
File exists

$ test -e /etc/passwd && echo "File exists"
File exists

より具体的には、評価は終了ステータスを介して他のコマンドに伝達されます。プログラムによっては、終了ステータスを出力して、さまざまなタイプのイベント(プログラムの正常終了、実行中に発生する特定のタイプのエラー、または構文エラー)を示すことができます。testコマンドの場合、0trueを1意味し、false を意味します。ステファンが指摘したように、構文エラーはの終了ステータスを生成します2

その場所はシステムによって異なりますman [。また、を実行したときにマニュアルページが表示されなかった理由も説明しています。たとえば、FreeBSDではの下にあり/binます。Linux(または私の特定の場合、Ubuntu 16.04)では、にあり/usr/bin/ます。あなたが行う場合man [またはman testLinuxシステム上で、開いている同じドキュメントを参照してくださいます。また、シェルがの独自の実装を持っている可能性があることに注意することも重要ですtest

また、このコマンドには問題があり、Kornシェルの実装(一般に二重角括弧付きの「条件式」参照として知られている[[ "$USER" = "root" ]])が解決しようとしています。この機能は、bashやなどの他のシェルでも使用されzshます。


/usr/bin/Amazon Linuxでも同様です。
フランクリンシジョ

@StéphaneChazelasありがとうございます。それに応じて編集された回答
Sergiy Kolodyazhnyy

3

どちらman [[ --help動作しません

一部のディストリビューション(Ubuntuなど)ではman [、へのシンボリックリンクをたどりますtest(1)。その他(Archなど)では、これは当てはまりません。(ただし、testmanページにも使用方法が記載さ[れています)


type -a [ シェル組み込みと実行可能ファイルの両方があることを示しています。

$ type -a [
[ is a shell builtin
[ is /usr/bin/[

bash-builtin [ --helpはエラーメッセージを出力するだけです。(ただし、組み込みであるためhelp [、を使用するか、bashのマニュアルページ/ドキュメントを参照してください)。

/usr/bin/[ --help (GNU Coreutilsバージョンの)完全なヘルプ出力を出力します。

$ /usr/bin/[ --help
Usage: test EXPRESSION
  or:  test
  or:  [ EXPRESSION ]
  or:  [ ]
  or:  [ OPTION
Exit with the status determined by EXPRESSION.

      --help     display this help and exit
      --version  output version information and exit

次に、EXPRESSIONに許可される構文について説明します。

これは、[それtestが同等であることがわかった別の方法です。


ところで、bash用にプログラミングしている場合(またはインタラクティブにワンライナーを記述している場合)、[[代わりにをお勧めします[。いくつかの点で優れています。Sergの回答のリンクを参照してください。


2

[引数に含まれるexpressionが真であると見なされる場合、コマンドは終了ステータス0を返し、引数に含まれるexpressionが偽であると見なされる場合、ゼロ以外の終了ステータスを返します。また、最後の引数がそうでない場合はエラーメッセージで失敗します](これは純粋に審美的な理由で行われます)。

例えば:

[ hello ]
echo "Exit-status of [ hello ] is:" $?
[ abc = abc ]
echo "Exit-status of [ abc = abc ] is:" $?
[ ]
echo "Exit-status of [ ] is:" $?
[ abc = def ]
echo "Exit-status of [ abc = def ] is:" $?

…出力されます:

[ハロー]の[終了ステータスは以下のとおりです。0       -非空の文字列が真であると見なされているため 
の出口状態[ABC = ABC]である:0   - 「ABC」は本当に「ABC」と同じであるため 
] [の出口ステータスです:1             —空の文字列はfalseと見なされるため 
[abc = def]の終了ステータスは次のとおりです。1   — 'abc'は実際には 'def'と異なるため

ただし、bashや他の多くのシェルは通常、これらのケースでは実際には呼び出し/bin/[(または/usr/bin/[)せず、代わりにまったく同じ動作で組み込みコマンドを呼び出します(純粋にパフォーマンス上の理由から)。/bin/[(シェルの組み込みサロゲートではなく)を呼び出すには、パスを明示的に指定する必要があります(例:/bin/[ hello ];を]介してdirname をプレフィックスする必要はありません)、または組み込みのサロゲートを使用しないようにシェルを構成する(たとえば、enable -n [bash)。

PS:他の回答で言われたように、[に関連していtestます。しかしtest、とは異なり[]最後の引数としては必要ありません(まったく期待していません; 引数に余分なもの]を追加testすると、エラーメッセージで失敗したり、間違った結果を返すことがあります)同じファイルに解決することができます(例えば、1つされるシンボリックリンクが、この場合には、行動の転換は、おそらくによって実現され、現在と呼ばれるコマンドを分析中に/のコード自体)、または別のファイルに。の場合、シェルは通常、パスが明示的に指定されている()か、そうでないように構成されていない限り(組み込みのサロゲートを呼び出します/bin/test/bin/[test[test/bin/testenable -n test)。

PPS:testおよびとは異なり[、modern ifは実際のファイルではありません。これはシェル(bashなど)構文の一部です:(if commandA; then commandB; fiセミコロンの代わりに改行を使用できます)ステータスがゼロで終了したcommandBif-and-only-ifが実行されcommandAます。これは、testまたはの動作に完全に適合し[、それらをif [ "$a" = foo ]; then …; fi (またはif test "$a" = foo; then …; fi-読みにくく)組み合わせることを可能にします。ただし、最近のスクリプト[[では、testまたはの代わりに[(としてif)実際のファイルではなく、常にシェル構文の一部として使用されることがよくあります。

PPPS:に関してはmanmanファイルシステムのすべてのコマンドに関する記事があるとは思わないでください。いくつかの(でも「リアル」、ファイルベース)コマンドは、特定のシェルに専用の物品内に多分存在するだけでなく、いくつかのシェル組み込みコマンドについての情報が欠落することができる(あなたが最も確かに情報を見つけるだろう場所ですその上の情報test[if[[)。それでも、多くのディストリビューションにはmantestとの明示的な記事があり[ます。(約--help、それtestは明白な理由で認識されません:のような静かなケースを処理する必要がありますa=--help; test "$a";いくつかのディストリビューションでは[ --help(閉じることなく])まだ助けを示しますが、そうでないものもあります。)


3
これifはUnix V6までのコマンドでした。Unix V7(1979)には、Bourneシェル(そのif-then-else-fi構成体)と新しいtestコマンドが付属していました。
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.