bashの条件式の-aと-eの違いは何ですか?


12

からman bash

CONDITIONAL EXPRESSIONS
[...]
       -a file
              True if file exists.
[...]
       -e file
              True if file exists.
  1. だから、何の違いである[ -a $FILE ]とは、[ -e $FILE ]任意の場合は、?
  2. 実際の違いがない場合、同じ目的で2つのフラグが存在するのはなぜですか?

開発者だけが#2を知っているでしょう---彼らがコミュニティに彼らの推論を共有しない限り。
ベルミンフェルナンデス2014

回答:


13

ではbash、2つの引数のコンテキストtestコマンドを使用-a file-e fileて、と同じです。しかし-a、2項演算子でもあるため、両者には多少の違いがあります。

-e単項はPOSIXで定義されていますが、単項は定義されて-aいません。POSIXは-aバイナリのみを定義します(テスト POSIXを参照)。

POSIXは、3つの引数のtest動作を定義します。

3つの引数:

  • $ 2がバイナリプライマリの場合、$ 1と$ 3のバイナリテストを実行します。

  • $ 1が '!'の場合、$ 2と$ 3の2つの引数のテストを否定します。

  • $ 1が '('で$ 3が ')'の場合、$ 2の単項検定を実行します。XSIオプションをサポートしないシステムでは、$ 1が '('で$ 3が ')'の場合の結果は不定です。

  • それ以外の場合、不特定の結果が生成されます。

だから-aまた奇妙な結果につながります:

$ [ ! -a . ] && echo true
true

-a3つの引数のコンテキストでは、2項演算子と見なされます。Bash FAQの質問E1を参照してください。POSIXは、それ-aがKornShellから取得したものであると述べていますが-e-aバイナリと-a単項を混同するため、後で変更されました。

シェルスクリプトがファイルを開こうとせずにファイルが存在するかどうかを確認する唯一の方法を提供するため、Cシェルによって提供される機能と同様の機能を備えた-eプライマリが追加されました。実装ではファイルタイプを追加できるため、移植可能なスクリプトでは以下を使用できません。

テスト-b foo -o -c foo -o -d foo -o -f foo -o -p foo

fooが既存のファイルかどうかを確認します。歴史的なBSDシステムでは、ファイルの存在は次のように判断できます。

テスト-f foo -o -d foo

しかし、既存のファイルが通常のファイルであると判断する簡単な方法はありませんでした。初期の提案ではKornShell -aプライマリ(同じ意味を持つ)を使用していましたが、-aプライマリと-aバイナリ演算子を混同する可能性が高いという懸念があったため、これを-eに変更しました。

-aバイナリは、式が曖昧になり、引数が4つ以上になるため、陳腐化のマークも付けられます。これらの4つ以上の引数式では、POSIXは結果が未指定であることを定義します。


知ってかっこいい!今はもう少し明確です:)!
polym 2014

9

.1。では、[-a $ FILE]と[-e $ FILE]の違いは何ですか(ある場合)。

全く違いはありません。

行の505-507test.cのbashのバージョンの4.2.45(1)-release

case 'a':           /* file exists in the file system? */
case 'e':
  return (sh_stat (arg, &stat_buf) == 0);

これは、両方のフラグに実際の違いがないことを示しています。

.2。実際の違いがない場合、同じ目的で2つのフラグが存在するのはなぜですか?

gnoucの回答を参照してください。


3
一方、それ-aがbashのブール演算子(および)でもあることを考えると、完全に冗長であるこの追加の意味を追加するバグが発生しやすいようです。私はそれが他のいくつかの実装との互換性や以前のバージョンとの互換性に関連していたと思います-e
celtschk 14

@celtschk-バグが発生しやすいわけはありませんが、シェルのパーサーがバグである可能性があります。POSIXを指定-aし、-oブール値のために[ test ]。しかし、一部のシェル(などbashは、引数と演算子を区別するの[ test ]が難しく、結果は信頼できませんでした。それ以降、POSIXは、準拠するシェルが[ test ]ブラケット内の少なくとも4つの引数を処理することを要求しています。
mikeserv 2014

5

私が見つけた最良の答えは、StackOverflowの質問からこれです:

-aは非推奨であるため、マンページには記載されてい/usr/bin/testませんが、bashにはまだ記載されています 。を使用し-eます。シングル '['の場合、bashビルトインはandとtest同じように動作するbashビルトインと同じように動作します (一方は他方へのシンボリックリンクです)。の効果はその位置に依存することに注意してください。最初にある場合は、を意味します。2つの式の中間にある場合は、論理を意味します。/usr/bin/[/usr/bin/test-afile existsand

[ ! -a /path ] && echo existsbashのマニュアルで-aは2項演算子と見なされているため、動作しません。上記はaとしてではnegate -a ..なく、if '!' and '/path' is true(空ではない)として解析されます。したがって、スクリプトは常に出力し"-a"(実際にはファイルをテストします)、"! -a"実際にはandここではバイナリ です。

の場合[[-aはバイナリとして使用されandなくなった(&&そこで使用されている)ため、その固有の目的はそこにあるファイルを確認することです(非推奨ですが)。したがって、否定は実際にあなたが期待することを行います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.