[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why tail coreutil cannot work as its input is from tee

From: Greg Wooledge
Subject: Re: Why tail coreutil cannot work as its input is from tee
Date: Mon, 6 Sep 2021 08:25:33 -0400

On Mon, Sep 06, 2021 at 07:38:03AM +0000, Budi wrote:
> How come tail coreutil cannot work as its input is from tee
> $ echo -e '9\n4\n3\n2\n8\n7\n3\n1' |tail -1
> 1
> But :
> $ echo -e '9\n4\n3\n2\n8\n7\n3\n1' |tee >(head -1) |tail -1
> 9
> Please help explain

It would be better if you explained what you actually want to do, so
that we can tell you a correct way to do it.

What you've got here is a race condition.  Your pipeline has three
commands in it.  The race condition is in the second command:

  ... | tee >(head -1) | ...

When the shell sets up this command, this is what happens:

1) Stdin is coming from an anonymous pipe already.  Call this "the
   input pipe".

2) A second anonymous pipe is created for the output, and stdout is
   redirected to that pipe.  Let's call this "the output pipe".

3) A background job is created to run "head -1".  This background job
   inherits stdout from its parent.  Therefore, the output of the
   "head -1" job will be the output pipe.

4) The stdout of tee is *also* the output pipe.

So, you have two processes both writing to the same output pipe: tee
and head.  The actual result you see will depend on which one
finishes writing its output last.  And also how the output is divided up
(i.e. whether the echo command writes it all in one atomic chunk, or
multiple chunks).

Your failing command is so abstract and "homework-y" that it's clearly
a !b9.  Nobody can tell what it was meant to do.  If you would please
tell us what you're *actually* trying to do, we could help you a lot more.

  9. All examples given by the questioner will be broken, misleading,
     wrong, incomplete, and/or not representative of the actual question.

My best guess about what you *thought* it would do is: print the first
and last lines of the input.

If you want to print the first and last lines of input, I would recommend
either sed or awk.

unicorn:~$ printf %s\\n {1..9} | sed -n -e 1p -e \$p

unicorn:~$ printf %s\\n {1..9} | awk 'NR==1 {print} END {print}'

If that's *not* what you want, then again, I implore you, please tell
us what you *do* want.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]