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

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

からman bash

CONDITIONAL EXPRESSIONS
[...]
       -a file
              True if file exists.
[...]
       -e file
              True if file exists.
  1. [ -a $FILE ][ -e $FILE ]では、その違いは何ですか?
  2. 実際の違いがなければ、同じ目的のために2つのフラグが存在するのはなぜですか?

答え1

bash2 つの引数があるコマンドのコンテキストではtest-a file-e fileは同じです。ただし、-a二項演算子でもあるため、若干の違いがあります。

-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 つの引数の文脈では、二項演算子として扱われます。バラよりバッシュFAQ問題E1。 POSIXでは、KornShellからのインポートについても言及しましたが、バイナリと単項を混同したため、後で変更され-aました。-e-a-a

デフォルトの-eを追加すると、ファイルを開こうとせずにファイルが存在するかどうかを調べるシェルスクリプトの唯一の方法を提供するという点で、Cシェルが提供するのと同様の機能があります。実装時に追加のファイル形式を追加できるため、移植可能なスクリプトは使用できません。

テスト -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は結果を指定しないように定義します。

答え2

.1.それでは、[ -a $FILE ]と[ -e $FILE ]の違いは何ですか?

まったく違いはありません。

バッシュバージョンから505-507test.c4.2.45(1)-release

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

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

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

バラよりcuonglmの答え

答え3

私が見つけた最良の答えは、StackOverflowに関する質問からのものです。

-a廃止予定のため、マンページには表示されなくなりますが、 /usr/bin/testbash マンページには引き続き表示されます。使用-e。単一の「[」の場合、bash組み込み機能はbash組み込み機能と同じように機能し、これはtestandと同じように機能します(1つは別のものへのシンボリックリンクです)。効果は場所によって異なります。先頭にあれば意味します。両方の式の中間にある場合、論理を表します。/usr/bin/[/usr/bin/test-afile existsand

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

for は[[もはや-aバイナリとして使用されないのでand&&もはや使用されていませんが)、独自の目的はそこからファイルをチェックすることです。したがって、否定は実際に期待どおりに機能します。

関連情報