パラメータ拡張に欠けている部分があるようです。

パラメータ拡張に欠けている部分があるようです。

私は現在単純なスクリプトを書く方法を学んでいますが、非常に単純な問題を解決することはできません。

私のスクリプトには次のコマンドがあります...

touch ${DIRECTORY}/${FILE}

このコマンドは私のスクリプトに何度も表示され、1つのインスタンスを除いてすべて正常に動作します。何らかの理由で、どの時点で作成したいファイル名にスラッシュを含めることにしましたが、エラーが発生しました。

cannot touch `/myfile.dat': Permission denied

当初、私はこれが私の経験の欠如によるものかもしれないと思いました(おそらくそうです)。しかし、いくつかの調査の後、私はこの行が多数の例でうまく機能することを発見しました。わかりません。同じ行が私のスクリプトの他のいくつかの場所でうまく動作します!

誰でも説明できますか?この不一致は私を本当に迷惑にさせます。その特定のコマンドに関連するコマンドは結果に影響しますか?

答え1

空のようです${DIRECTORY}。この場合、タッチは${DIRECTORY}/${FILE}次に拡張されます。touch /${FILE}

答え2

いろいろなことが起こります。

  • この時点でタイプミスが発生した可能性があるため、DIRECTORYスクリプトが設定されていないtouch ${DRIECTORY}/${FILE}ため、isの場合は次のように拡張されます(未設定の変数は空であると見なされます)。設定されていない変数を展開しようとするたびに、エラーメッセージとともにシェルが停止することがあります。スクリプトの上部(この行の後ろ)にあります。とを使用して、unset-triggers-errorとunset-is-emptyの間を前後に切り替えることができます。DIRECTORY$FILEmyfile.dattouch /${FILE}
    set -u#!set -uset +u
  • DIRECTORY現在の変数は設定されていないか空である可能性があります。前のトピックを参照してください。
  • 誤ってスペースを追加した可能性がありますtouch ${DIRECTORY} /${FILE}。その後、コマンドtouchは2つの引数を使用してその引数に対して動作し${DIRECTORY}(既存のディレクトリの名前である可能性があるため、そのディレクトリの変更時間を現在の時刻に設定します)/${FILE}
  • 値の末尾に余分なスペースがあるかもしれませんDIRECTORY。たとえば、変数の/some/path値に末尾のスペースが含まれている場合は、touch2つの引数/some/pathとを受け取ります/myfile.dat。前のトピックを参照してください。

DIRECTORYFILEスペースやワイルドカードが含まれていると、スクリプトは機能しません\[?*。これは、egを作成するときに$FOO変数値としてのみ拡張されないためです。値はスペースの各シーケンスで単語に分割され、各単語はワイルドカードパターンとして解釈され、一致するファイル名に置き換えられます(ファイル名が一致しない場合はパターンが保持されます)。変数の置換(および同様にコマンドの置き換え)には常に二重引用符を使用してください。二重引用符内では、追加の変更なし"$FOO"で値に拡張されます。FOO

touch "$DIRECTORY/$FILE"

(あなたも見ることができます$VAR対${VAR}と引用)

スクリプトが何をするのかをよりよく理解するには、set -xこの#!行の後に置きます。これにより、シェルが各コマンドを実行する前に印刷するデバッグモードが有効になります。set -xとを使ってデバッグトレースをオンまたはオフにできますset +x

関連情報