Re: |& in bash?

2013-01-22 Thread Steven W. Orr

On 1/21/2013 1:20 PM, John Caruso wrote:

In article , Dan Douglas wrote:

It isn't very common to dump multiple streams into one pipe.


echo "n't very"  >/dev/null 2>&1


I suggest avoiding |&.


Personally I wouldn't use it in scripts, since I try to stick as close
to plain vanilla Bourne shell as possible (though that's not as much of
a consideration these days as it used to be).  But for interactive use
it's one of the greatest shell time- and effort-savers I know of, and
I'm very happy to hear it's made its way into bash.  I wouldn't suggest
avoiding it unless you like carpal tunnel.

- John



Just an old observation. I much prefer use of |& for the simple reason that it 
provides greater consistency.


foo > out 2>&1
The above uses the file out to capture stdout and stderr. The order of 
evaluation is important and if you were to say

foo 2>&1 > out
it wouldn't work because you would be redirecting stderr to stdout before 
stdout was redirected to a file.


By that logic,

foo 2>&1 | bar

should not work, but it does. It takes stderr and dups it to stdout, and 
*then* takes stdout and send it to a pipe.


The proper way that it should have been done (if I was Emperor of the 
Universe) would have been


foo | 2>&1 bar

I accept that the | delimits what happens in the two different processes, so 
this is not material subject to a jihad. Just an observation from a language 
lawyer.


--
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



Re: |& in bash?

2013-01-22 Thread Greg Wooledge
On Tue, Jan 22, 2013 at 06:56:31AM -0500, Steven W. Orr wrote:
> By that logic,
> 
> foo 2>&1 | bar
> 
> should not work, but it does. It takes stderr and dups it to stdout, and 
> *then* takes stdout and send it to a pipe.

Incorrect.  The pipeline is created first, and *then* the dup (2>&1) is
performed.

Also, "takes stderr and dups it to stdout" is backwards.  It is taking
stdout (1) and dup'ing that and putting the duplicate FD into stderr (2).
I like to read "2>&1" as "make 2 be a copy of 1".

So, in chronological order:

0) Bash sets up a new execution environment (forking, or saving FDs in
   temporary FDs, or whatever it has to do to clean the slate).
1) A pipe is created.  This gives us two new FDs.
2) Bash creates two new processes and connects stdout of the first process
   to the pipe's "write FD", and connects stdin of the second process to
   the pipe's "read FD".
3) Within the first child process, stdout (which happens to be pointing
   to the pipe) is duplicated, and the duplicate FD is stored in stderr (2).
   Therefore, stderr is *also* pointing to the pipe.
4) The first process execs "foo".  The second process execs "bar".
   Meanwhile, the parent process (bash) waits for them to complete.
5) foo and bar do whatever they do.  Eventually they stop running.  Bash
   wakes up and moves on to the next command.



Re: |& in bash?

2013-01-22 Thread Bob Proulx
Greg Wooledge wrote:
> On Tue, Jan 22, 2013 at 06:56:31AM -0500, Steven W. Orr wrote:
> > By that logic,
> > [...alternate possibility omitted...]
> 
> So, in chronological order:
> [...list of actions omitted...]

I think the take-away here is that the shell evolved to require 142
unique command line scanning actions (obviously I am greatly
exagerating that number) in order to perform the complex task that it
must perform.  That is more steps than the human brain is casually
comfortable remembering.

As tired and sleepy humans our brains would like the number of actions
to be no greater than 2 in order to easily hold it in our head.  We
stretch it to 3, to 4 to 5 but at some point we run out of fingers and
the number might as well actually be 142.  By the time we reach the
number of steps that are really needed, what the shell does, it is too
many and doesn't stick in our heads.

Perhaps there is a one-sheet poster hint sheet with all of the shell
command line scanning steps nicely illustrated that we could post on
the wall so that we can glance up and refresh our memory of it when
needed.  Something like the [fill in your favorite programming
language here] operator precedence table.  (If you looked over at your
copy next to you then you know what I am talking about.)

Bob



Re: |& in bash?

2013-01-22 Thread Andreas Schwab
Greg Wooledge  writes:

> On Tue, Jan 22, 2013 at 06:56:31AM -0500, Steven W. Orr wrote:
>> By that logic,
>> 
>> foo 2>&1 | bar
>> 
>> should not work, but it does. It takes stderr and dups it to stdout, and 
>> *then* takes stdout and send it to a pipe.
>
> Incorrect.  The pipeline is created first, and *then* the dup (2>&1) is
> performed.

This is true, but not obviously so.  If you have the rule "redirections
are processed from left to right", then this looks like an outlier (if
you treat the pipe as another kind of redirection).

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."



Re: |& in bash?

2013-01-22 Thread DJ Mills
On Tue, Jan 22, 2013 at 1:45 PM, Andreas Schwab wrote:

> This is true, but not obviously so.  If you have the rule "redirections
> are processed from left to right", then this looks like an outlier (if
> you treat the pipe as another kind of redirection).
>
>
And that's the issue, a pipe is *not* just another kind of redirection,
it's much more than that.


Re: |& in bash?

2013-01-22 Thread Greg Wooledge
On Tue, Jan 22, 2013 at 07:45:10PM +0100, Andreas Schwab wrote:
> Greg Wooledge  writes:
> > On Tue, Jan 22, 2013 at 06:56:31AM -0500, Steven W. Orr wrote:
> >> foo 2>&1 | bar
> > The pipeline is created first, and *then* the dup (2>&1) is
> > performed.
> This is true, but not obviously so.  If you have the rule "redirections
> are processed from left to right", then this looks like an outlier (if
> you treat the pipe as another kind of redirection).

Well... that's the way the shell works.  It's one of the things you need
to understand if you're working with complex shell scripts.  Even if
the Bash |& extension is embraced by the community, you'll still need
to understand how foo 2>&1 | bar works if you're doing work in POSIX or
Bourne shells.

It kinda reminds me of the Linux newcomers who don't know how to do
gzip -dc foo.tar.gz | tar xvf - (and so on) because they've been trained
to use GNU tar's "z" flag instead, and therefore that piece of their
education hasn't been absorbed yet.



Re: |& in bash?

2013-01-22 Thread Bob Proulx
Greg Wooledge wrote:
> It kinda reminds me of the Linux newcomers who don't know how to do
> gzip -dc foo.tar.gz | tar xvf - (and so on) because they've been trained
> to use GNU tar's "z" flag instead, and therefore that piece of their
> education hasn't been absorbed yet.

Just like:

  grep -r PATTERN

Has replaced:

  find . -type f -exec grep PATTERN {} +

And therefore they don't know how to write other directory traversal
tasks either.

  find . -type f -exec sed -n '/PATTERN/s/THIS/THAT/gp' {} +

Bob