Bash IF ステートメントが期待どおりに機能しません。

Bash IF ステートメントが期待どおりに機能しません。

この単純なBashスクリプトのロジックを理解できません。

#!/bin/bash

# Check if file is present
which ./vendor/bin/non_existent_file &> /dev/null

printf "Exited with $?\n\n"

if [[ "$?" -eq 1 ]]; then
  echo "Number is One"
else
  echo "Number is not one"
fi

ファイルが見つからない場合(存在しない場合)、出力は次のようになります。

Exited with 1

Number is not one

ファイルが存在する場合、出力は次のようになります。

Exited with 0

Number is not one

???

私が試したこと:

if [ $? == 1 ]
if [ "$?" == 1 ]
if [[ "$?" == 1 ]]
if [[ $? -eq 1 ]]
if [[ "$?" = "1" ]]
if [[ "$?" == "1" ]]

IF文が常に失敗するのはなぜですか?

答え1

which ./vendor/bin/non_existent_file &> /dev/null

これにより終了ステータスが実行され、which設定されます。$?(これはwhich今あなたに効果があると思います。)

printf "Exited with $?\n\n"

これにより終了ステータスが実行され、printf設定されます。$?

if [[ "$?" -eq 1 ]]; then

したがって、テストされるのは終了状態ですprintf

これを防ぐには、終了ステータスを一時変数に保存する必要があります。

which ./vendor/bin/non_existent_file &> /dev/null
ret=$?
printf 'which exited with status %d\n' "$ret"
if [[ $ret -ne 0 ]]; then
    printf "that was a falsy exit status"
fi

私が知っている限り、指定された実行可能ファイルがwhich検索されますが、固定パスを見ている場合は、ファイルが実行可能かどうかを直接確認するために使用できます。でプログラムを探している場合は、確認してください。PATH[[ -x ./path ]]PATH「which」を使わないのはなぜですか?それでは何を使うべきですか?警告と極端なケース。

答え2

コメントありがとうございました@Kusalanandaと@SottoVoceに感謝します。

$?を含む前のコマンドの結果を保存しますprintf

したがって、実行が正常に実行されたため、実行がにprintf "Exited with $?\n\n"変わります。$?0

これらの混乱を避けるために、実行結果を別の変数に保存することをお勧めします。

関連情報