できると思います
$ [ -w /home/durrantm ] && echo "writable"
writable
または
$ test -w /home/durrantm && echo "writable"
writable
または
$ [[ -w /home/durrantm ]] && echo "writable"
writable
3番目の構文を使用するのが好きです。それらはすべての点で同等であり、すべてのネガティブおよびエッジケースと同等ですか?移植性に違いはありますか? UbuntuのbashとOS Xまたはそれより古い/新しいbashバージョンの間。 4.0の前/後、両方とも同じように式を展開しますか?
[
はtest
コマンドの同義語であり、同時にbashビルトインおよび個別のコマンドです。ただし、[[
はbashキーワードであり、一部のバージョンでのみ機能します。したがって、移植性の理由から、単一の[]
またはtest
を使用するほうがよいでしょう。
[ -w "/home/durrantm" ] && echo "writable"
はい、違いがあります。最も移植性が高いのはtest
または[ ]
です。これらは両方とも POSIX test
仕様 の一部です。
if ... fi
構成要素も POSIX によって定義されており、完全に移植可能である必要があります。
[[ ]]
はksh
機能であり、bash
の一部のバージョンにも存在します( すべての最新バージョン )、zsh
およびおそらく他の場所にありますが、sh
またはdash
またはその他のさまざまな単純なシェルにはありません。
したがって、スクリプトを移植可能にするには、[ ]
、test
またはif ... fi
を使用します。
[] && cmd
はif .. fi
構成と同じではないことに注意してください。
時々その動作はかなり似ており、[] && cmd
の代わりにif .. fi
を使用できます。しかし、ときどき。 if条件またはif .. else .. fi
が必要な場合に実行するコマンドが複数ある場合は、ロジックに注意してください。
いくつかの例:
[ -z "$VAR" ] && ls file || echo wiiii
と同じではありません
if [ -z $VAR ] ; then
ls file
else
echo wiii
fi
ls
が失敗した場合、echo
は実行されますが、if
では発生しません。
もう一つの例:
[ -z "$VAR" ] && ls file && echo wiii
と同じではありません
if [ -z "$VAR" ] ; then
ls file
echo $wiii
fi
この構造は同じように動作しますが
[ -z "$VAR" ] && { ls file ; echo wiii ; }
エコー後の;
は重要であり、そこにある必要があることに注意してください。
上記のステートメントを再開すると、
[] && cmd
==最初のコマンドが成功した場合、次のコマンドを実行します
if .. fi
==条件(テストコマンドの場合もあります)の場合、コマンドを実行します
そのため、[
と[[
の間の移植性のために、[
のみを使用してください。
if
はPOSIX互換です。したがって、[
とif
のどちらかを選択する必要がある場合は、タスクと期待される動作を確認することを選択してください。
実際にはif
ではなくtest
を置き換えるのは&&
です。シェルスクリプトのif
ステートメントは、コマンドが「成功」(ゼロ)を返したかどうかをテストします)終了ステータス。あなたの例では、コマンドは[
です。
したがって、実際にはここで2つの点が異なります。テストを実行するために使用するコマンドと、そのテストの結果に基づいてコードを実行するために使用する構文です。
テストコマンド:
test
is 標準化されたコマンド 文字列とファイルのプロパティを評価します。あなたの例では、コマンドtest -w /home/durrantm
を実行しています[
は、同等に標準化されたそのコマンドのエイリアスであり、括弧で囲まれた式のように見えるように、]
の必須の最後の引数があります。だまされてはいけません、それはまだ単なるコマンドです(あなたのシステムには/bin/[
というファイルがあるかもしれません)[[
は、一部のシェルに組み込まれたtestコマンドの拡張バージョンですが、同じPOSIX標準の一部ではありません。ここには使用していない追加オプションが含まれています条件式:
&&
演算子( ここでは標準化 )は、2つのコマンドを評価し、両方が0を返す場合は0(trueを表す)を返すことにより、論理AND演算を実行します。最初のコマンドがゼロを返した場合にのみ2番目のコマンドを評価するため、単純な条件式として使用できますif ... then ... fi
構文( ここでは標準化 )は、「真理」を判断する同じ方法を使用しますが、then
句内のステートメントの複合リストではなく、 &&
ショートサーキットによって提供されるコマンド、およびElif
句とelse
句を提供します。これらの句は、&&
と||
だけを使用して書き込むのは困難です。 if
ステートメントでは、条件の前後に角括弧がないことに注意してください。したがって、次の例はすべて移植可能であり、完全に同等であり、例のレンダリングになります。
test -w /home/durrantm && echo "writable"
[ -w /home/durrantm ] && echo "writable"
if test -w /home/durrantm; then echo "writable"; fi
if [ -w /home/durrantm ]; then echo "writable"; fi
次のものも同等ですが、[[
の非標準的な性質のため、移植性は低くなります。
[[ -w /home/durrantm ]] && echo "writable"
if [[ -w /home/durrantm ]]; then echo "writable"; fi
移植性を確保するには、test
/[
を使用します。ただし、移植性が必要ない場合は、自分自身およびスクリプトを読む他の人の健全性のために、[[
を使用します。 :)
BashFAQ のWhat is the difference between test, [ and [[ ?
も参照してください。
ボーンのような世界の外での移植性が必要な場合は、次のようにします。
test -w /home/durrantm && echo writable
最もポータブルです。 Bourne、csh
およびrc
ファミリーのシェルで動作します。
test -w /home/durrantm && echo "writable"
writable
ファミリのシェルでrc
ではなく"writable"
を出力します(rc
、es
、akanga
、"
は特別ではありません)。
[ -w /home/durrantm ] && echo writable
[
に$PATH
コマンドがないシステムのcsh
またはrc
ファミリーのシェルでは機能しません(test
ですが、その[
エイリアスは除きます)。
if [ -w /home/durrantm ]; then echo writabe; fi
bourneファミリのシェルでのみ機能します。
[[ -w /home/durrantm ]] && echo writable
ksh
(元の場所)、zsh
、bash
(Bourneファミリの3つすべて)でのみ機能します。
必要なfish
シェルでは機能しません。
[ -w /home/durrantm ]; and echo writable
または:
if [ -w /home/durrantm ]; echo writable; end
どちらかを選択する最も重要な理由if foo; then bar; fi
またはfoo && bar
は、コマンド全体の終了ステータスが重要かどうかです。
比較:
#!/bin/sh
set -e
foo && bar
do_baz
と:
#!/bin/sh
set -e
if foo; then bar; fi
do_baz
彼らは同じことをしていると思うかもしれません。ただし、foo
が失敗した場合(または、視点に応じてfalseの場合)、最初の例では、スクリプトが終了しているため、do_bazは実行されません... set -e
は、コマンドがfalseステータスを返した場合にシェルをすぐに終了するように指示します。次のような場合に非常に役立ちます。
cd /some/directory
rm -rf *
何らかの理由でcd
が失敗した場合にスクリプトの実行を継続する必要はありません。