他の誰もが言ったように、$dnam変数には二重引用符が必要です。理由は次のとおりです。
はコマンド[ ... ]のエイリアスです。testシステムを調べると、/bin/[or Maybeという名前のファイルが表示されます/bin/usr/[。/bin/test一部のシステムでは、これはまたはへのハード リンク/bin/usr/testです。ifステートメントはの後に続くものを実行ifし、そのコマンドがゼロの終了ステータスを返す場合、ステートメントは句ifを実行します。thenそれ以外の場合、else句があれば、代わりにそれが実行されます。
ブール値のテストを可能にするために、Unix にはtestコマンドが含まれているため、次のようにすることができます。
if test -d "$directory"
then
echo "Directory $directory exists!"
fi
後で、/bin/[がシンタックス シュガーとして追加されました。これは上記と同じです:
if [ -d "$directory" ]
then
echo "Directory $directory exists!"
fi
現在、 と は両方とも[組み込みtestコマンドですが、*まだコマンドです。これは、シェルがコマンドを補間してから実行することを意味します。
以下を実行してみてください。
$ set -xv # Turns on shell debugging
$ dnam="/home/bryan/renametest/C D"
dnam="/home/bryan/renametest/C D"
+ dnam='/home/bryan/renametest/C D'
$ test -d $dnam
test -d $dnam
+ test -d /home/bryan/renametest/C D
$ echo $?
echo $?
+ echo 1
1
$ test -d "$dnam" # Now with quotes
test -d $dnam
+ test -d "/home/bryan/renametest/C D"
$ echo $?
echo $?
+ echo 0
0
$ set +xv # Turn off the debuggin
各コマンドは 2 回エコーされます。1 回目はそのままで、2 回目はラインが補間された後です。補間の一部として、シェルはパラメーターを空白で分割します。ご覧のとおり、testコマンドは/home/bryan/renamtest/Cwhich が存在しないため、書き込み可能ではないかどうかをテストしています。test追加のパラメーターを渡したためにコマンドがエラー メッセージを出力しなかったことに、私は実際に驚いています。
2 回目の試行では、引用符を追加しました。これらの引用符は、シェルがスペースでパラメーターを分割するのを防ぎ、ディレクトリ名を単一のパラメーターとして保持します。
はコマンドであるため[ ... ]、シェルによる変数の補間やその他の問題を考慮する必要があります。また、十分に注意しないと、エラーが発生する可能性があります。
さらに悪いことに、[ ... ]うまくいくこともあれば、うまくいかないこともあります。ディレクトリ名にスペースが含まれていない場合は、期待どおりに機能します。あなたがプログラムを書いていて、それをテストすると、試したすべてのディレクトリにスペースが含まれていないため、すべてが機能すると想像してください。次に、誰かがあなたのプログラムを使用しますが、ディレクトリにスペースがあります。シェル スクリプトのかなりの数のバグが、ifステートメント内のこの種の問題に対して行われています。
これが、Bash が[[ ... ]]テストを導入した理由です。コマンドで[[はなく、ステートメントです。これは、シェルが結果を直接補間しないことを意味します。代わりに、パラメーターが解析され、補間が行われます。したがって、これはうまくいったでしょう:
dnam="/home/bryan/renametest/C D" # No "$" in front of the variable!
# Is the directory writable
if [[ ! -w $dnam ]] # No quotation marks needed!
then
# Not writable. Pop the error and exit.
echo "Directory $dnam is not writable"
err=1
fi
ほとんどの場合、[[ ... ]]テストよりもテストを使用する方が良い[ ... ]ため、先に進んで習慣を身につけてください。
もう 1 つ小さなエラーがあります。
$dnam="/home/bryan/renametest/C D"
これはシェルによって補間されるため、設定される変数は$dnamたまたまの値になります。たまたま「foo」と等しい場合$dnamは、次のようにします。
foo="/home/bryan/renametest/C D"
あなたが望むものではありません。
$変数を設定するときにオフのままにしたい:
dnam="/home/bryan/renametest/C D"