[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: printf "%q" and $'...'
From: |
Greg Wooledge |
Subject: |
Re: printf "%q" and $'...' |
Date: |
Wed, 25 Nov 2009 09:26:03 -0500 |
User-agent: |
Mutt/1.4.2.3i |
On Wed, Nov 25, 2009 at 02:35:51PM +0100, Antonio Macchi wrote:
> it sounds strange, beacuse
>
> $ find . -print0 | while read -d $'\x00'; do touch "$REPLY"; done
>
> works fine.
>
>
> but if I try to "output" $'\x00', I can't.
There's a lot going on here, so I'll try to cover it as best I can.
When you run read -d $'\x00' what you're really doing is setting up
a bunch of C-strings in memory like this:
+-+-+-+-+--+-
|r|e|a|d|\0|
+-+-+-+-+--+-
+-+-+--+-
|-|d|\0|
+-+-+--+-
+--+--+-
|\0|\0|
+--+--+-
That is, you're explictly creating a C-string whose content is a NUL
byte, and then it ends with another NUL byte. When the read command
gets around to reading these strings to see what its arguments are,
it sees the last string above as '' (an empty string), because the
first NUL it sees marks the end of the content.
read -d $'\x00' is completely equivalent to read -d '' and you may
find the latter to be a bit less typing.
The next issue is that you _can_ output a NUL byte, for example by using
printf:
imadev:~$ printf 'foo\0' | od -t x1
0000000 66 6f 6f 0
We don't pass a literal NUL byte to printf, because it would get lost in
the C-string (interpreted as an end-of-string marker). We send a
backslash-zero pair instead, and printf knows to treat that as a NUL
when writing its output.
In general, NULs can be read and written, and stored in files, but they
can't be stored in a bash variable. Nor can they appear in a command
argument. A NUL in a command argument causes the argument to be truncated
as you'd expect if you're a C programmer:
imadev:~$ echo $'foo\0bar'
foo
Contrast that with the printf '\0' command.