私はこの実験(Bashでの)で混乱しています:
$ mkdir 'foo\n'
$ find . -print0 | od -c
0000000 . \0 . / f o o \ n \0
0000012
ご覧のとおり、「find」は出力をnull文字で正しく区切っていますが、ディレクトリ名の改行を「foo\n」としてバックスラッシュ「n」でエスケープしています。なぜこれを行うのですか? 「これにより、改行を含むファイル名が、find出力を処理するプログラムによって正しく解釈されるようになります」と言いました。 「\ 0」は区切り文字であり、「\ n」ではないため、エスケープは必要ありません。
問題はfind
ではなく、このディレクトリの作成方法にあります。一重引用符で囲まれた文字列'foo\n'
は、実際には5文字の文字列で、最後の2つはバックスラッシュと小文字の "n"です。
シェルで二重引用符で囲まれた文字列はエスケープ文字としてバックスラッシュを使用するため、二重引用符も役に立ちませんが、Cスタイルのバックスラッシュシーケンスは実際には解釈されません。
Bashやzshなどのシェル(Debian/Ubuntuのダッシュではありません)では、$'...'
を使用して、これらのシーケンスを解釈できます。
$ mkdir $'foo\n'
(この機能についてはbashの documentation を参照してください。これは「ANSI Cクォーティング」と呼ばれます)。
ボーンシェルと互換性のあるシェルで機能する別のオプションは、actual改行を挿入することです。
$ mkdir 'foo
'
それは実際です Return 1行目の終わりでは、2行目の単一引用符のみを閉じます。
foo
という名前のディレクトリと改行を作成してみましょう。
$ mkdir $'foo\n'
次に、findを使用します。
$ find . -print0 | od -c
0000000 . \0 . / f o o \n \0
0000011
\n
はエスケープされません。
問題は、mkdir 'foo\n'
がfoo
の後に\
が続き、n
が続くと解釈されることです。次の方法で確認できます。
$ printf '%s' 'foo\n' | od -c
0000000 f o o \ n
0000005