Bashは内部的にCスタイルの文字列を使用し、ヌルバイトで終了します。これは、Bash文字列(変数の値、コマンドへの引数など)に実際にNULLバイトが含まれることがないことを意味します。たとえば、このミニスクリプト:
foobar=$'foo\0bar' # foobar='foo' + null byte + 'bar'
echo "${#foobar}" # print length of $foobar
実際に印刷し3ているため、$foobarただ実際には'foo':bar文字列の末尾の後に来ます。
同様に、パーツを知らないため、echo $'foo\0bar'単にprintします。fooecho\0bar
ご覧のように、\0シーケンスは実際には$'...'-style文字列では非常に誤解を招きます。文字列内ではヌルバイトのように見えますが、そのようには機能しません。最初の例では、readコマンドにはがあり-d $'\0'ます。これは機能しますが、それ-d ''も機能するからです!(これはの明示的に文書化された機能ではありませんreadが、同じ理由で機能すると仮定します:''空の文字列であるため、その終端のヌルバイトがすぐに来ます。「デリムの最初の文字」を使用して文書化され、 「最初の文字」が文字列の終わりを超えている場合!)-d delim
あなたから知っているとしてではなくfind例として、それはあるヌルバイトをプリントアウトするためのコマンドについて、および入力として、それを読み込み、別のコマンドにパイプされるそのバイトに対して可能。Bash内の文字列に nullバイトを格納することに依存する部分はありません。2番目の例の唯一の問題は$'\0'、コマンドの引数で使用できないことです。echo "$file"$'\0'あなたがそれを望んでいることがわかっている場合に限り、最後にnullバイトを喜んで印刷することができます。
したがって、を使用する代わりに、を使用してecho、-style文字列printfと同じ種類のエスケープシーケンスをサポートでき$'...'ます。そうすれば、文字列内にヌルバイトを入れなくても、ヌルバイトを印刷できます。次のようになります。
for file in * ; do printf '%s\0' "$file" ; done \
| while IFS= read -r -d '' ; do echo "$REPLY" ; done
または単にこれ:
printf '%s\0' * \
| while IFS= read -r -d '' ; do echo "$REPLY" ; done
(注:echo実際には、nullバイトを-e処理\0して印刷できるフラグもありますが、ファイル名に含まれる特別なシーケンスを処理しようとするため、このprintfアプローチはより堅牢です。)
尚、一部のシェルがあります nullは内部の文字列をバイト許します。たとえば、Zshでの例は正常に機能します(デフォルト設定を前提としています)。ただし、シェルに関係なく、Unixライクなオペレーティングシステムは、プログラムへの引数にヌルバイトを含める方法を提供しません(プログラムの引数はCスタイルの文字列として渡されるため)。常にいくつかの制限があります。(あなたの例では、という理由だけでZshの中で作業することができますechoZshのは、他のプログラムを呼び出すためのOSのサポートに頼ることなく、それを呼び出すことができますので。あなたが使用している場合、シェル組み込みであるcommand echo代わりにしecho、それは組み込みをバイパスし、スタンドアロンで使用ようechoにプログラムを$PATH、 ZshでBashと同じ動作が見られます。)
-d ''すでに区切りを意味する場合、IFSが何も設定されないのはなぜ\0ですか?ここで説明を見つけました:stackoverflow.com/questions/8677546/…–