0

I have following response checker in a script:

#!/bin/bash

test_fn()
{
WARNFILE=$1
echo
echo "--- BEGIN ---"
cat ${WARNFILE}
echo "--- END ---"
echo

while true; do
    read -r -n 1 -p "Continue? [y/n]: " REPLY
    case $REPLY in
      [yY]) break ;;
      [nNqQ]) echo;exit ;;
      *) printf "\033[31m%s\033[0m\n" " invalid input: ${REPLY}"
    esac
done
}

test_fn /tmp/warning 

it works fine...

$ ./test.sh

--- BEGIN ---
test warning
--- END ---

Continue? [y/n]: a invalid input: a
Continue? [y/n]: s invalid input: s
Continue? [y/n]: d invalid input: d
Continue? [y/n]: w invalid input: w
Continue? [y/n]: s invalid input: s
Continue? [y/n]: q
$

...until I change line:

test_fn /tmp/warning

with line:

test_fn /tmp/warning | tee -a /tmp/logfile

then, it scrambles lines:

$ ./test.sh

--- BEGIN ---
test warning
Continue? [y/n]: --- END ---

aContinue? [y/n]:  invalid input: a
sContinue? [y/n]:  invalid input: s
dContinue? [y/n]:  invalid input: d
fContinue? [y/n]:  invalid input: f
q
$

Anyone could please tell why it works so?

2
  • 4
    It's because read is writing the prompt to stderr but you are only redirecting stdout to tee I think; that results in the original stderr getting intermixed with the teed stdout. Try test_fn /tmp/warning 2>&1 | tee -a /tmp/logfile Commented Mar 24, 2018 at 13:29
  • @steeldriver, indeed, you are absolutely right, thank you. Commented Mar 24, 2018 at 17:42

1 Answer 1

1

To convert a comment to an answer:

read -p writes the prompt to stderr; in order to get the results in-line for tee, pipe the function's stderr to stdout before the tee with:

test_fn /tmp/warning 2>&1 | tee -a /tmp/logfile

To demonstrate read's behavior:

$ read -p "my prompt: " >/dev/null
my prompt: hi
$ read -p "my prompt: " 2>/dev/null
hi

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.