web-dev-qa-db-ja.com

引用符のないファイルでは、どの文字をエスケープする必要がありますか?

Bashコマンドを実行するブラウザベースのシェル/ターミナルを使用していて、スペースをエスケープしていますが、括弧もエスケープする必要があることがわかりました。引用符で囲まれていないファイル名をエスケープする必要がある他の文字は何ですか?

12
jcubic

簡単な解決策は、最初に単一引用符(_'_)を置き、最後に別の単一引用符を置き、ファイル名内のすべての_'_文字を4文字のシーケンス_'\''_。文字列の終わりを示す_'_自体を除いて、すべての文字は一重引用符で囲まれた文字列内では特別な意味を失います。シーケンス_'\''_は、単一引用符付きリテラルを終了し、直後に引用符付き単一引用符を続け、新しい単一引用符付きリテラルを開きます。したがって、ファイル名

_This file's name has some weird characters!
Will you manage to escape them?
_

次のように引用することができます:

_somecommand 'This file'\''s name has some weird characters!
Will you manage to escape them?'
_

二重引用符にはより複雑なエスケープルールがあり、履歴置換が有効になっている場合は感嘆符_!_を含めることができないため、これ以上は考慮しません。

別のアプローチは、バックスラッシュで文字を保護することです。これは、改行を除くすべての文字で機能します。改行の場合、単一引用符(または二重引用符)で囲むことが唯一の解決策です。引用符で囲まれた名前をユーザーに提示するためにバックスラッシュの数を最小限にしたい場合は、バックスラッシュが必要な場所に制限することができます。ただし、省略したバックスラッシュが多いほど、必要なものを忘れるリスクが高くなります。文字、数字、非ASCII文字は常に使用できます。不明な場合は、空白や句読点を引用してください。

一般的なシェル(ksh、bash、またはzsh)では、少なくともいくつかの状況では、次の文字を引用符で囲む必要があります。

  • 空白(スペース、タブ、改行—改行はバックスラッシュで引用できないことに注意)。
  • _!_ —履歴の拡張。
  • _"_ —シェルの構文。
  • _#_ —コメントの前に空白を置くと開始します。 zshワイルドカード。
  • _$_ —シェルの構文。
  • _&_ —シェルの構文。
  • _'_ —シェルの構文。
  • _(_ — Wordの途中でも:ksh拡張グロブ(bashおよびzshでも使用可能)。 zshワイルドカード。
  • _)_(_(_を参照)
  • _*_ — shワイルドカード。
  • _,_ —ブレース展開内のみ。
  • _;_ —シェル構文。
  • _<_ —シェル構文。
  • _=_ — zshでは、ファイル名の先頭にある場合(PATHルックアップによるファイル名の展開)。
  • _>_ —シェル構文。
  • _?_ — shワイルドカード。
  • _[_ — shワイルドカード。
  • _\_ —シェル構文。
  • _]_ —引用符を付けずに済む場合があります。
  • _^_ —履歴の拡張。 zshワイルドカード。
  • _`_ —シェル構文。
  • _{_ —ブレース展開。
  • _|_ —シェル構文。
  • _}_ — zshではエスケープする必要があります。他のシェルは、対応する開始中括弧がない場合の方が寛大です。
  • _~_ —ファイル名の先頭にある場合のホームディレクトリの展開。 zshワイルドカード。それが最後の文字であるときは常に安全です。

さらにいくつかの文字には、特別な処理が必要になる場合があります。

  • _-_はシェルにとって特別ではありませんが、コマンド引数の先頭にある場合は、オプションを示します。特別な処理はシェルではなくコマンドで行われるため、引用符で保護することはできません。 _-_で始まるファイル名を保護するために、その前に_./_を置くことができます。これにより、同じファイルのままですが、引数が_-_で始まっていません。
  • _._自体は特別ではありませんが、ドットファイルはデフォルトで_*_グロブから除外されます。
  • _:_はシェルにとって特別ではありませんが、一部のコマンドはそれを特別に解析します。リモートファイルを示します(_hostname:filename_)。コロンを含むファイル名に対処する方法については、コマンドのドキュメントを参照してください。

¹ ユーザーが代替履歴拡張文字を構成していない限り。一部のシェルではこれが可能です。これは、バックスラッシュではなく単一引用符を使用するもう1つの理由です。