This line writes "foo", sleeps, and then writes "bla":
echo "woo"; sleep 2; echo "bla"
I'm trying to read the entire output of this, in two sequential read commands:
(echo "woo"; sleep 2; echo "bla") 1> \
>(IFS=""; read -t 0.1 -r -N 10; \
echo "exit code: $? reply: $REPLY"; \
sleep 5; \
read -t 0.1 -r -N 10; \
echo "exit code: $? reply: $REPLY")
The first read prints:
exit code: 142 reply:
which is kinda expected, since 142 is a timeout, and I called read with -t 0.1. But the second read prints:
exit code: 1 reply: bla
Question: where did "woo" go?!
If I remove the sleep 2
from the output line, the whole thing works as expected -- reads/outputs the entire "woo\nbla" sequence in the first read, and returns 1 (EOF).
The problem reproduces with any sleep, no matter how short. It also doesn't matter if I use a pipe to redirect output instead of >1. This is Ubuntu.
Edit: I want to read into a buffer of N characters, and read the input as-is, without any word-splitting on delimeters. Hence the -N and IFS="".
Edit: this is a toy example to demonstrate a general problem. What I'm trying to do is to implement a smarter version of tee in bash: it should behave like tee, except it should wait for its input-generating process to stop, then flush its buffers, and exit. The real tee hangs indefinitely if the input-generating process starts some zombie child processes, because they then occupy the stdout handle and it never gets closed. Using tail --pid works, but unfortunately it doesn't work on Windows, and I need this to be multi-platform. I thought this could be accomplished by calling read -t -N in a loop, but apparently that doesn't work...
The exit status is greater than 128 Interactive bash scripts are nothing without catching user input. The read builtin provides methods that user input may be caught within a bash script. To catch a line of input NAMEs and options are not required by read. When NAME is not specified, a variable named REPLY is used to store user input.
Read is a bash builtin command that reads the contents of a line into a variable. It allows for word splitting that is tied to the special shell variable IFS. It is primarily used for catching user input but can be used to implement functions taking input from standard input. Bash read builtin command help
When catching user input without it showing up int the terminal, the -s option comes in handy. read -s -p allows you to catch and hide user input as follows. Here are examples of functions in bash that use read and standard input Functions using read make use of piped standard input and parameters.
To read input from the keyboard and assign input value to a variable use the read command. If you don’t give any argument to the read command, input will assign to the environment variable REPLY. The “s” option does not echo input while reading from a keyboard. The -p “TEXT” option displays TEXT to the user without a newline.
Question: where did "woo" go?!
The woo
was read by the first read -t 0.1 -r -N 10
and then this command failed, because it did not receive 10 characters or EOF character within the set timeout.
According to the read man page:
-N nchars return only after reading exactly NCHARS characters, unless EOF is encountered or read times out, ignoring any delimiter -t timeout time out and return failure if a complete line of input is not read withint TIMEOUT seconds. The value of the TMOUT variable is the default timeout. TIMEOUT may be a fractional number. If TIMEOUT is 0, read returns success only if input is available on the specified file descriptor. The exit status is greater than 128 if the timeout is exceeded
Edit: I want to read into a buffer of N characters, and read the input as-is, without any word-splitting on delimeters. Hence the -N and IFS="".
If you call read
command two times, each instance of it has a separate buffer. To solve this use a single read
command and adjust or remove the timeout option eg:
(echo "woo"; sleep 2; echo "bla") 1> \
>(IFS=""; read -r -N 10; \
echo "exit code: $? reply: $REPLY";)
And then, if you want to simultaneously view the incoming input, you can add the tee
command, eg:
(echo "woo"; sleep 2; echo "bla") 1> \
>(tee >(IFS=""; read -r -N 10; \
echo "exit code: $? reply: $REPLY";))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With