bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[BUG] builtin read from pipe (echo foo | read) does not affect the resul


From: Eddy Razanajatovo
Subject: [BUG] builtin read from pipe (echo foo | read) does not affect the result variable
Date: Wed, 12 Dec 2001 14:16:58 +0100

Summary:
Under RedHat Linux 7.0 (i386) (this may affect other Linux distributions and
versions), the "read" builtin function does consume a line from standard
input, BUT it does not perform the variable assignment, when the standard
input is coming from a shell pipe.

Diagnostic:
It seems that "read" fails to detect that the standard input is not a
terminal. So it performs tty-related functions that fail when applied to a
pipe (for example controlling the user input mode). Bash builtin "read"
command exits silently and does not affect the specified variable(s) or the
default REPLY variable.
Another possible reason would be that Bash incorrectly assumes that "read"
is reading from a terminal if the self process standard input is a terminal,
despite its input may have been temporarily redirected. However, "read" is a
builtin, so it runs in the context of the bash shell process itself, which
is interactive and has a standard input connected to the terminal. The
builtin "read" should check the status of its input and not assume that it
is the same as the process standard input. While the pipe is active, the
controling terminal is still a console, however the standard input is not a
terminal.

Samples (under bash or sh):
$ bash --version
GNU bash, version 2.04.11(1)-release (i386-redhat-linux-gnu)
Copyright 1999 Free Software Foundation, Inc.
$ bash
$ echo "foo" | read
$ echo $REPLY # should display "foo":

$ echo "bar" | read VAR
$ echo $VAR # should display "bar":

$ export VAR
$ VAR=""
$ echo "foobar" | read VAR
$ echo $VAR # should display "foobar":

$exit

This affects many shell scripts that should run non interactively and that
need to parse an input file line after line, generated by another tool (for
example awk), so that the result output can be captured and parsed
appropriately.

Workaround:
Don't use pipe, but redirection to and from a temporary file (for example
/tmp/bashbug.$$):

Caveats:
The workaround requires filespace space in a temporary directory, and
commands do not perform concurrently, as in the following example:

#!/bin/bash
(
    perform_something_that_generates_a_big_file_on_stdout
) | (
    while read
    do
        manage_a_result_line $REPLY
    done
)

Note that this affects bash even if it is invoked in Bourne-Shell mode using
"sh" or "/bin/sh" instead of "bash".
So the above example must be rewritten as:

#!/bin/bash
(
    perform_something_that_generates_a_big_file_on_stdout
) > /tmp/bashbug.$$ ; (  /bin/rm -f /tmp/bashbug.$$
    while read
    do
        manage_a_result_line $REPLY
    done
) < /tmp/bashbug.$$





reply via email to

[Prev in Thread] Current Thread [Next in Thread]