2

ディレクトリが絶対に書き込み可能であるのに、これが常に書き込み可能でないと言っている理由を誰か教えてもらえますか?

    $dnam="/home/bryan/renametest/C D"

    # ディレクトリは書き込み可能ですか
    エラー=0
    もしも [ !-w $dnam ]
    それから
        # 書き込み不可。エラーをポップして終了します。
        echo "ディレクトリ $dnam は書き込み可能ではありません"
        エラー=1
    フィ
4

3 に答える 3

0

複数の問題があります。

  • 変数内にスペースを使用しています。これは違法ではありませんが、組み合わせ行でエスケープされていない変数を使用し、次のコマンドを生成します。

    if [ ! -w /home/bryan/renametest/C D ]
    

    これは有効な構文ではありません。これを修正する最も簡単な方法は、行を次のように変更することです

    if [ ! -w "$dnam" ]
    
  • 次の問題はもっと悪いです: 私のシステムでhelp testは、テキストを返します:

    -w FILE        True if the file is writable by you.
    

    つまり、コマンドはディレクトリをサポートせず、ファイルのみをサポートします。ディレクトリが書き込み可能かどうかを確認したい場合は、別のコマンドを使用する必要があります

于 2015-04-15T14:23:15.763 に答える
0

他の誰もが言ったように、$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"
于 2015-04-15T14:56:13.240 に答える