6

So far, I know the piping mechanism as a way to connect a series of commands by connecting the stdout of one command to the stdin of the next command until the last command is reached, which connects its stdout with the display or a file.

Would it be possible, however, to make a loop out of commands, so the last command's stdout connects to the first command's stdin and maybe by using tee somehow the changing values of a certain output could be displayed?

6
  • 4
    I edited your post with a personal opinion; feel free to revert it, of course, but I'm just trying to keep the question clear and ... non-revolting.
    – Jeff Schaller
    May 27, 2017 at 20:13
  • if I made a calvinistic protestant happy by improving the world by making it more like god imagined it with the power of the holy editor function, I am more than pleased
    – sharkant
    May 27, 2017 at 20:18
  • 2
    Do you have a use case for where something like this would be a solution? Or is it a purely intellectual exercise?
    – Kusalananda
    May 27, 2017 at 20:33
  • i am bloody beginner, thus I do not know enough for making reasonable solutions for anything, so like chanting A B C i am bound to intellectual exercises and speculations, hoping not asking too stupid questions or becomming notorious for contributing waste without benefit
    – sharkant
    May 27, 2017 at 20:39
  • 1
    @JeffSchaller I was like "what could Jeff possibly mean, revolting" and then i clicked the edit history
    – cat
    May 28, 2017 at 1:57

3 Answers 3

7

I'm not sure about all the shells there are, but in Bash it's possible, though not with unnamed pipes. So not with the | symbol. But if you create a named pipe:

mkfifo fifo

Then you can use it:

<fifo cat | cat >fifo &

Now the pipeline works in the background, but does nothing. But if you feed the pipe from outside the pipeline:

echo x >fifo

The pipeline will unblock and go on forever. Or until you drain the pipe:

cat fifo

The output will appear once:

x

To make this a little sophisticated, the pipeline may be this:

<fifo cat | xargs -I@ echo @x >fifo &

So it will add an x to the output at each iteration. Of course it will, but only once the iterations start, meaning as soon as the pipe unblock, that is as soon as there's something to read. As previously, this can be started by hand:

echo x >fifo

And now take a look at what top shows. There should be quite a lot of activity of both cat and xargs.

And the same as before, if you drain the pipeline, you should see a lot of xs in the terminal, and the pipeline will block.

It would be a valid question, why does the pipeline get drained. Why is the cat command committed in the terminal leaving nothing in the circuit. I don't know this.

2
  • 3
    This is heavily dependent on the size of the standard IO buffer size. If any data between two parts of the pipeline exceeds the buffer size, the pipeline would block.
    – Kusalananda
    May 27, 2017 at 20:53
  • @Kusalananda That will be the limit. And it may be an answer why the pipeline gets drained.
    – user147505
    May 27, 2017 at 20:55
2

Well you certainly could by just make a loop and use variables:

while true; do
    a=$(echo "$a" | grep "Hey" | cut -d" " -f2 | tee -a log)
done

That would save the last output which would be used at the beginning again

4
  • a = command1|command2|command3 so this structure would save the std output of command3 into variable a, but what if command3 does not have one but a series of values?
    – sharkant
    May 27, 2017 at 20:49
  • 1
    It would all be saved as one whole string in the Variable a and be used again in command 1
    – ADDB
    May 27, 2017 at 20:51
  • 2
    I'm not sure if this answers the actual question: that's a whole different kind of a loop.
    – ilkkachu
    May 28, 2017 at 8:30
  • Nah it doesn't, he accepted it just for fun. He asked how do built a loop that's using the stdout as stdin, and that is what this loop does
    – ADDB
    May 28, 2017 at 8:32
0

As the existing answer, looped pipeline is not possible in Unix shell without using named pipe (created using mkfifo(1)). But you can do it in C; for example here's my dirty-simple implementation, that didn't even wait for processes to exit.

I hope you find this information useful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.