Just a remark about the sub shell usage in bash in comparision to ksh. Let's try:
strace -f -o bash.strace bash -c 'echo a b | read a b' and grep about execve, clone, write on stdout, read from stdin: > grep -E 'execve|clone|write\(1|read\(0' bash.strace 17183 execve("/bin/bash", ["bash", "-c", "echo a b | read a b"], [/* 99 vars */]) = 0 17183 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7d61708) = 17184 17183 clone( <unfinished ...> 17183 <... clone resumed> child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7d61708) = 17185 17184 write(1, "a b\n", 4 <unfinished ...> 17185 read(0, "a", 1) = 1 17185 read(0, " ", 1) = 1 17185 read(0, "b", 1) = 1 17185 read(0, "\n", 1) = 1 and now the same with the Korn shell strace -f -o ksh.strace ksh -c 'echo a b | read a b' > grep -E 'execve|clone|write\(1|read\(0' ksh.strace | sed 's/^/ /' 17198 execve("/bin/ksh", ["ksh", "-c", "echo a b | read a b"], [/* 99 vars */]) = 0 17198 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7bb3918) = 17199 17199 write(1, "a b\n", 4) = 4 17198 read(0, <unfinished ...> as now is visible the last command in the pipe sequence done in the bash is a real sub process whereas in the ksh it is not. The question rises: Why does the bash require a sub peocess/shell for the final command of a pipe sequence. Werner -- "Having a smoking section in a restaurant is like having a peeing section in a swimming pool." -- Edward Burr