Here is an example of using dd to trigger a shell command whenever something is read from stdin, whether terminated by newline or not:
{
printf not-nl-terminated
sleep 1
printf '%s\n' nl-terminated
sleep 1
echo
sleep 1
printf 'binary\0data'
} |
while : ; do
input=$(dd bs=1M count=1 2>/dev/null | tr '\n\0' __)
[ "$input" ] || break
printf 'input of size %d\n' "${#input}"
done
will give
input of size 17
input of size 14
input of size 1
input of size 11
This snippet from the standard spec may help understand dd's behavior when bs= is used explicily:
If the bs= expr operand is
specified and no conversions other than sync, noerror, or notrunc
are requested, the data returned from each input block shall be
written as a separate output block; if the read returns less than a
full block and the sync conversion is not specified, the resulting
output block shall be the same size as the input block. If the bs=
expr operand is not specified, or a conversion other than sync,
noerror, or notrunc is requested, the input shall be processed and
collected into full-sized output blocks until the end of the input
is reached.