I've been trying to figure out why I get a literal end-of-transmission character (EOT, ASCII code 4) in my variable if I read Ctrl+D with read -N 1
in bash
and ksh93
.
I'm aware of the distinction between the end-of-transmission character and the end-of-file condition, and I know what Ctrl+D does when using read
without -N
(it sends EOT, and if the input was empty, the underlying read()
returns zero, signalling EOF).
But I'm not sure why trying to read a specific number of characters changes this behaviour so radically. I would have expected an EOF condition and that the following loop would exit:
while read -N 1 ch; do
printf '%s' "$ch" | od
done
Output when pressing Ctrl+D:
0000000 000004 0000001
The bash
manual says about read -N
(ksh93
has a similar wording):
-N nchars
; read returns after reading exactlynchars
characters rather than waiting for a complete line of input, unless EOF is encountered or read times out.
... but it says nothing about switching the TTY to raw/unbuffered mode (which is what I assume is happening).
The -n
option to read
seems to work in the same way with regards to Ctrl+D, and the number of characters to read doesn't seem to matter either.
How may I signal an end-of-input to read -N
and exit the loop (other than testing the value that was read), and why is this different from a "bare" read
?
read -e -N 1 ch
works fine.-e
options involves bash readline for interactive shells... Maybe this means thatread -N
works in a non interactive way while simpleread
works interactivelly.-e
it's more complicated, but it's still not a true EOF (you can see that withread -e -N 2 ch
). I suppose that's a bug, i.e. the EOF should be emulated in both cases.