Petr Razumov
Petr Razumov

Reputation: 2152

read builtin doesn't work with pipe

I'd like to ask user a confirmation to read from stdin (Display output [Y/n]). It works Ok if some arguments were provided, or no arguments were provided but there was some input. However, if some data was piped to the script, there's no confirmation.

#!/bin/bash

output_file=$(mktemp)

cleanup() {
    rm -f "$output_file"
}

trap cleanup 0 1 2 3 15

if [ $# -gt 0 ]; then
    while [ $# -gt 0 ]; do
        echo "$1" >> "$output_file"
        shift
    done
else
    while read -r line; do
        echo "$line" >> "$output_file"
    done
fi

while true; do
    read -p "Display output? [Y/n]" response
    if [ -z "$response" ]; then
        break
    fi

    case $response in
        [Yy]*) break;;
        [Nn]*) exit;;
    esac
done

less "$output_file"

What prevent read -p to work? What should be done to provide consistent behavior?

Upvotes: 0

Views: 172

Answers (2)

ccarton
ccarton

Reputation: 3666

The read command reads input from standard in. If you have standard in fed from a pipe then read looks for its data from the pipe, not from your terminal.

On most platforms you can work around this by redirecting the read command's input directly from the tty device, as in:

read -p "Display output? [Y/n]" response </dev/tty

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 755016

If the script read everything from standard input, what is the read -p going to get? And it likely doesn't prompt if the input is not an 'interactive device' (aka terminal). Have you checked the Bash man page for read? It says:

-pprompt
Display prompt, without a trailing newline, before attempting to read any input. The prompt is displayed only if input is coming from a terminal.

When your input is from a pipe, it is not from a terminal.

Upvotes: 1

Related Questions