Shell tips and tricks

Steven W. Orr steveo at syslang.net
Thu Nov 1 16:47:21 EDT 2007


On Thursday, Nov 1st 2007 at 15:26 -0000, quoth VirginSnow at vfemail.net:

=>> Date: Thu, 1 Nov 2007 13:09:00 -0400
=>> From: "Ben Scott" <dragonhawk at gmail.com>
=>
=>>   Sheesh.  That makes even less sense to me.  Let me see if I have
=>> this right.  Two examples:
=>> 
=>> 	foo | while read LINE ; do bar ; i=$(( i + 1 )) ; done
=>> 
=>> 	while read LINE ; do bar ; i=$(( i + 1 )) ; done < <(foo)
=>> 
=>> The first results in the "do clause" being run in a subshell, while
=>> the second does not?  Why is that?  In both cases, we're sending
=>> output from one process into the shell's internal "read" builtin.  Is
=>> there any rhyme or reason to this?

This is interesting because what you're really generating here is a 
detached process  which is running foo and which is writing to a pty. That 
pty is being read by your shell script. The end result is that the while 
loop in this case is *not* in the scope of a child process created by a 
pipe. Don't forget: pipe in shell is not pipe(2). Pipe in shell is a whole 
sequence of fork/dup/pipe/close/exec calls.

=>
=>It's because the former example uses the itsy bitsy oh-so-narrow
=>who-ever-woulda-thought such-a-small-character could-cause-so-much
=>trouble "|" character.  Using "|" is roughly equivalent to doing a
=>fork() and hooking file descriptors up so that one process's outputs
=>go to the other process's inputs.  Each time you add "| blah" to a
=>command, bash automatically forks & shuffles file descriptors.
=>

On Thursday, Nov 1st 2007 at 15:42 -0000, quoth Ben Scott:

=>On 11/1/07, VirginSnow at vfemail.net <VirginSnow at vfemail.net> wrote:
=>> Using "|" is roughly equivalent to doing a fork() and hooking file descriptors
=>> up so that one process's outputs go to the other process's inputs.
=>
=>  Right, but doesn't the Process Substitution do a similar thing?  My
=>question is not "Why does a subshell ever get used at all?", but "Why
=>is a subshell used sometimes but not others?".  Again, compare these
=>two:
=>
=>	foo | while read LINE ; do bar ; i=$(( i + 1 )) ; done
=>
=>	while read LINE ; do bar ; i=$(( i + 1 )) ; done < <(foo)
=>
=>  For the second example, the shell has to fork() and exec() the "foo"
=>program, and hook up it's stdout file descriptor to the stdin file
=>descriptor that gets passed to the "do clause".  Why doesn't that need
=>a subshell?

The | character is *exactly*  the same as the whole meshugena sequence you 
have to do in C of fork/close/dup/pipe/exec nonsense. It would make zero 
sense for access to variables which happen to have the same name on 
opposite side of the pipe to be the same instance. :-)

-- 
Time flies like the wind. Fruit flies like a banana. Stranger things have  .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net


More information about the gnhlug-discuss mailing list