ifステートメントでリダイレクトを使用したりファイルに書き込んだりすると、終了コードにどのように影響しますか?

ifステートメントでリダイレクトを使用したりファイルに書き込んだりすると、終了コードにどのように影響しますか?

存在する扱いにくい

echo 'a string' > test.txt
echo $?
0

そして

[[ $(echo 'a string') ]]
echo $?
0

しかし、

[[ $(echo 'a string' > test.txt) ]]
echo $?
1

他の例

curl -so 'curl-8.2.1.tar.gz' https://curl.se/download/curl-8.2.1.tar.gz
echo $?
0

または

[[ $(curl -so 'curl-8.2.1.tar.gz' https://curl.se/download/curl-8.2.1.tar.gz) ]]
echo $?
1

私の質問:

  1. 出力リダイレクトのためですか?そうでなければ、その理由は何ですか?
  2. コマンドの実行に成功しました。a string表示されtest.txt、カールが私が指定した出力ファイルにファイルをダウンロードします。評価結果はなぜ現れますかfalse
  3. スクリプトでこれを処理するための合理的な方法はありますか?特定のコマンドを実行したいとしましょう。前のコマンドが正常に実行されたがまだ返されたfalse場合、どのように実行する必要がありますか?その行が表示されるか、ファイルがダウンロードされたことを確認するために2番目のチェックを追加できますが、最初にコマンドが正常に実行されたかどうかを評価する必要はありません。

追加の完全性の例(読みやすさと「正確さ」?):

if ( $(echo 'a string' > text.txt) ); then echo yes; else echo no;fi
yes
if (( $(echo 'a string' > text.txt) )); then echo yes; else echo no;fi
no
if $(echo 'a string' > text.txt); then echo yes; else echo no;fi
yes
if echo 'a string' > text.txt; then echo yes; else echo no;fi
yes

答え1

$?

内部にシェルによって設定されたパラメータman部分zshparam、つまりinfo zsh 'Parameters Set By The Shell' あなたが見ることは、$?最後のコマンドによって返された終了状態です。

$(...)

人ではzshexpn以下info zsh 'Command Substitution'を見ることができます。

コマンドの置き換え

'$(...)'括弧で囲まれ、前にドル記号(例:)が含まれているか、アクセントとして引用されたコマンド(例:)は、末尾の ...改行文字が削除された標準出力に置き換えられます。

たとえば、式は末尾の改行文字が削除された$(echo 'a string')コマンド()の出力に置き換えられます。ただし、内部コマンドは標準出力で出力を生成しないため、式の結果は空の文字列です。a string<newline>a string$(echo 'a string' > test.txt)

[[ ... ]]

zshmiscまたは、マンページにinfo zsh 'Conditional Expressions'次のように表示されます。

条件式

条件式は複合コマンドと共に使用され、ファイル属性を[[テストし、文字列を比較します。各式は、次の単項式またはバイナリ式のうちの1つ以上で構成できます。

[...]

互換性のために構文上重要でない引数(通常は変数)がある場合、条件は次のように処理されます。 式がゼロ以外の文字列に拡張されるかどうかをテストします。

今、

したがって、次の行では、コマンドの出力は文字列である$( ... )ためa string<newline>、自己拡張子は長さがゼロ以外の文字列であるため、$(...)計算はtrue(0終了状態)を返します。a string[[ ... ]]

[[ $(echo 'a string') ]]

ただし、次のコマンドはリダイレクトしたため、拡張は長さ$( ... )0の文字列になり、[[ ... ]]計算はfalse(ゼロ以外の数字である終了ステータス1)を返します。

[[ $(echo 'a string' > test.txt) ]]

同様に、次のコマンドの終了状態はcurlこのコマンドの終了状態です。

curl -so 'curl-8.2.1.tar.gz' https://curl.se/download/curl-8.2.1.tar.gz

will マンページcurlでは、ゼロ以外の(失敗)終了状態を返す条件について説明します。

ただし、次の例では、終了ステータスは、curlコマンドに出力があるか(成功)、出力がないか(失敗)によって異なります。

[[ $(curl -so 'curl-8.2.1.tar.gz' https://curl.se/download/curl-8.2.1.tar.gz) ]]

(( ... ))ここで止まります。ただし、マニュアルを読み続けることもできます。算術評価人の一部zshmisc(またはinfo zsh 'Arithmetic Evaluation'

答え2

[[ ... ]]成功したコマンドの実行がコマンドの出力結果がゼロ以外の文字列になるように理解されていない限り、usingは成功したコマンドの実行を評価するのに適していないと結論付けます。 zshスクリプトで確認する場合、正しい方法は次のとおりです。

  1. if command; then ...; [else ...;] fi(muruの説明に記載されているように使用されます)
  2. コマンドを単独で実行し、$?後で終了コードを確認してください。および/または
  3. たとえば、生成されたファイルの内容を調べて、コマンドの実際の出力を確認します。

関連情報