$ '\ 0'が ''と同じ理由は何ですか?

$ '\ 0'が ''と同じ理由は何ですか?

複数のファイルで操作を実行する一般的な方法は次のとおりです。これについて私を非難しないでください。

for f in $(ls); do …

スペースやその他の奇妙な文字を含むファイルから安全にするには、次の簡単な方法に従ってください。

find . -type f -print0 | while IFS= read -r -d '' file; …

ここ-d ''に図のようにASCII NUL設定の略語を示します-d $'\0'

ところで、なぜそうなのか?なぜ''そして$'\0'同じですか? Bash Cルートの空の文字列は常にnullで終わるからですか?

答え1

これman page of bash内容は次のとおりです。

          -d delim
                 The first character of delim is  used  to  terminate  the
                 input line, rather than newline.

文字列は通常 null で終わるため、空の文字列の最初の文字は null バイトです。 - 合理的だと思います。 :)

ソースは次のように書きました。

static unsigned char delim;
[...]
    case 'd':
      delim = *list_optarg;
      break;

空の文字列の場合はdelimnull バイトです。

答え2

bashには互いに補完する2つの欠陥があります。

これを作成すると、$'\0'内部的には空の文字列と同じように扱われます。たとえば、

$ a=$'\0'; echo ${#a}
0

bashは内部的にすべての文字列を次のように格納するためです。文字列、彼らnullで終了- NULLバイトは文字列の終わりを示します。 Bashは文字列を最初のnullバイト(文字列の一部ではない)まで自動的に切り捨てます。

# a=$'foo\0bar'; echo "$a"; echo ${#a}
foo
3

-d組み込みオプションに文字列を引数として渡すと、readbashは文字列の最初のバイトのみを調べます。しかし、実際に文字列が空でないことを確認するわけではありません。内部的には、空の文字列は、nullバイトのみを含む1要素バイト配列として表されます。したがって、bashは文字列の最初のバイトを読み取るのではなく、nullバイトを読み込みます。

その後、内部的に組み込み関数の背後にあるメカニズムは、区切りread文字が見つかるまでバイト単位でnullバイトを処理し続けます。

他のシェルは異なる動作をします。たとえば、ash と ksh は、入力を読み取るときに null バイトを無視します。 ksh を使用してksh -d ""改行文字が表示されるまで読みます。シェルは、バイナリデータではなくテキストとうまく機能するように設計されています。 Zshは例外です。 zsh は、任意のバイト (ヌルバイトを含む) を処理する文字列表現を使用し、$'\0'長さが 1 の文字列です (ただし、read -d ''奇妙にも同様に動作しますread -d $'\0')。

関連情報