Re: |& in bash?
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?
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?
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?
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?
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?
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?
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