Bash – Reading multiple files one line at a time in bash

bashread

I know the basic way of reading from a command in bash:

cal | while IFS= read -r line ; do 
    echo X${line}X
done

But what if I want to read one line from several files/commands in a loop? I've tried named pipes but they'd only spit out one line.

$ cal > myfifo &
$ IFS= read -r line < myfifo
[cal exits]
$ echo $line
   February 2015      

So what I'd really want is something like:

while [all pipes are not done]; do
    IFS=
    read line1 < pipe1    # reading one line from this one
    read line2 < pipe2    # and one line from this one
    read line3 < pipe3    # and one line from this one
    print things with $line1 $line2 and $line3
done

Big picture what I'm trying to do is process three different months from cal to do some colorizing for use with Conky. It's a bit of yak shaving, honestly, so has become academic and a 'learning experience' at this point.

Best Answer

paste would be the tidiest way to do it. But, with bash file descriptors and process substitutions:

exec 3< <(cal 1 2015)
exec 4< <(cal 2 2015)
exec 5< <(cal 3 2015)

while IFS= read -r -u3 line1; do
    IFS= read -r -u4 line2
    IFS= read -r -u5 line3
    printf "%-25s%-25s%-25s\n" "$line1" "$line2" "$line3"
done

exec 3<&-
exec 4<&-
exec 5<&-
    January 2015             February 2015             March 2015          
Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     
             1  2  3      1  2  3  4  5  6  7      1  2  3  4  5  6  7     
 4  5  6  7  8  9 10      8  9 10 11 12 13 14      8  9 10 11 12 13 14     
11 12 13 14 15 16 17     15 16 17 18 19 20 21     15 16 17 18 19 20 21     
18 19 20 21 22 23 24     22 23 24 25 26 27 28     22 23 24 25 26 27 28     
25 26 27 28 29 30 31                              29 30 31                 
Related Question