From: Robert Latest on
Hello people,

the snippet from an interactive bash session below should illustrate my
"problem". Stuff on the right-hand side are my comments for the
respective line. I attempted assigning hours and minutes from date's
output to a couple of variables using 'read':


$ date '+%H +%M' | read h m ; echo $h $m | First try
| ... prints empty line
$ read h m ; echo $h $m | Huh? Can't 'read' read from stdin??
10 20 | This was typed in by hand
10 20 | Sure enough: correct output
$ cat | read h m ; echo $h $m | Let's pipe stdin through cat
11 22 | This was typed in
10 20 | h and m still have the old values
$ eval `date '+h=%H; m=%M'` ; echo $h $m | This is what I ended up doing
21 38 | ... with the correct result

In short: Why doesn't 'read' assign any values to variables h and m
when stdin comes in from a pipe?

Thanks,
robert
From: Edgardo Portal on
On 2010-01-15, Robert Latest <boblatest(a)yahoo.com> wrote:
> Hello people,
>
> the snippet from an interactive bash session below should illustrate my
> "problem". Stuff on the right-hand side are my comments for the
> respective line. I attempted assigning hours and minutes from date's
> output to a couple of variables using 'read':
>
>
> $ date '+%H +%M' | read h m ; echo $h $m | First try
> | ... prints empty line
> $ read h m ; echo $h $m | Huh? Can't 'read' read from stdin??
> 10 20 | This was typed in by hand
> 10 20 | Sure enough: correct output
> $ cat | read h m ; echo $h $m | Let's pipe stdin through cat
> 11 22 | This was typed in
> 10 20 | h and m still have the old values
> $ eval `date '+h=%H; m=%M'` ; echo $h $m | This is what I ended up doing
> 21 38 | ... with the correct result
>
> In short: Why doesn't 'read' assign any values to variables h and m
> when stdin comes in from a pipe?
>
> Thanks,
> robert

FWIW, I noticed the same thing recently when porting some
ksh scripts from an old-ish Solaris to bash on Linux. Turned
out that bash doesn't work the way ksh does in this
respect:

jim(a)katie:~$ echo $SHELL
/bin/bash

jim(a)katie:~$ date +'%H %M' | read h m; echo $h $m

jim(a)katie:~$ ksh

u@h:w$ date +'%H %M' | read h m; echo $h $m
15 53

Didn't bother to debug it, just installed ksh on Linux
and moved on.
From: pk on
Robert Latest wrote:

> the snippet from an interactive bash session below should illustrate my
> "problem". Stuff on the right-hand side are my comments for the
> respective line. I attempted assigning hours and minutes from date's
> output to a couple of variables using 'read':
>
>
> $ date '+%H +%M' | read h m ; echo $h $m | First try
> | ... prints empty line
> $ read h m ; echo $h $m | Huh? Can't 'read' read from
> stdin??
> 10 20 | This was typed in by hand
> 10 20 | Sure enough: correct output
> $ cat | read h m ; echo $h $m | Let's pipe stdin through cat
> 11 22 | This was typed in
> 10 20 | h and m still have the old
> values
> $ eval `date '+h=%H; m=%M'` ; echo $h $m | This is what I ended up doing
> 21 38 | ... with the correct result
>
> In short: Why doesn't 'read' assign any values to variables h and m
> when stdin comes in from a pipe?

See this page:

http://mywiki.wooledge.org/BashFAQ/024
From: Jerry Peters on
Robert Latest <boblatest(a)yahoo.com> wrote:
> Hello people,
>
> the snippet from an interactive bash session below should illustrate my
> "problem". Stuff on the right-hand side are my comments for the
> respective line. I attempted assigning hours and minutes from date's
> output to a couple of variables using 'read':
>
>
> $ date '+%H +%M' | read h m ; echo $h $m | First try
> | ... prints empty line
> $ read h m ; echo $h $m | Huh? Can't 'read' read from stdin??
> 10 20 | This was typed in by hand
> 10 20 | Sure enough: correct output
> $ cat | read h m ; echo $h $m | Let's pipe stdin through cat
> 11 22 | This was typed in
> 10 20 | h and m still have the old values
> $ eval `date '+h=%H; m=%M'` ; echo $h $m | This is what I ended up doing
> 21 38 | ... with the correct result
>
> In short: Why doesn't 'read' assign any values to variables h and m
> when stdin comes in from a pipe?
>
> Thanks,
> robert

Read does assign the values, the problem is that read is running in a
child shell which cannot affect the values of h and m in the parent
shell. Try a here document:

read h m <<-EOF
date '+%H %M'
EOF

Process substitution should also work.


Jerry
From: mop2 on
On Fri, 15 Jan 2010 18:48:08 -0200, Robert Latest <boblatest(a)yahoo.com> wrote:

> Hello people,
>
> the snippet from an interactive bash session below should illustrate my
> "problem". Stuff on the right-hand side are my comments for the
> respective line. I attempted assigning hours and minutes from date's
> output to a couple of variables using 'read':
>
>
> $ date '+%H +%M' | read h m ; echo $h $m | First try
> | ... prints empty line
> $ read h m ; echo $h $m | Huh? Can't 'read' read from stdin??
> 10 20 | This was typed in by hand
> 10 20 | Sure enough: correct output
> $ cat | read h m ; echo $h $m | Let's pipe stdin through cat
> 11 22 | This was typed in
> 10 20 | h and m still have the old values
> $ eval `date '+h=%H; m=%M'` ; echo $h $m | This is what I ended up doing
> 21 38 | ... with the correct result
>
> In short: Why doesn't 'read' assign any values to variables h and m
> when stdin comes in from a pipe?


As already said by others, your read is running in a subshell.
Pass the read command to the current shell:

read h m <<<`date '+%H %M'`


As reference, a quick test with various shell:

$ for s in /bin/*sh;do printf "$s \t:";$s -c 'printf "\t$h $m\t:\t";read h m <<<`date "+%H %M"`;echo $h $m';done
/bin/ash :Syntax error: redirection unexpected
/bin/bash : : 22 27
/bin/csh :Missing name for redirect.
/bin/ksh : : 22 27
/bin/rksh : : 22 27
/bin/sh : : 22 27
/bin/tcsh :Missing name for redirect.
/bin/zsh : : 22 27
$