Home > front end >  Redirect a pipe chain
Redirect a pipe chain

Time:09-17

Let's suppose the output of a chain of pipes command1 | command2 | comamnd3 is the name of a file and you want to redirect < this file to another command.

I'd like to use something like command4 < command1 | command2 | comamnd3 but it seems that < operator has preference over |

For example, I can search for the "hello" word in the most recent file doing:

grep "hello" $(ls -t | head -n1)

But, how to do that without the using of subshells, just using pipes and redirections? I.e grep "hello" < ls -t | head -n1 (*)

(*) Yes, I know I don't need redirection for grep. This is just an example

CodePudding user response:

You should rely on sub shells by:

( command4 < command1 ) | command2 | comamnd3

CodePudding user response:

command4 < command1 | command2 | comamnd3

Why don't move your command to the end of pipechain, as it should be logical? :

command1 | command2 | command3 | command4

| is not just a redirection, it is pipe with redirection between two separate processes, when < and > are redirection of stdout/stdin belong to the same process, that is why they executes before '|' pipe.

If you want to put your command4 in the beginning by any personal reasons, you can use ( ) to join other commands, like that:

command4 < ( command1 | command2 | command3 )

And your example:

grep "hello" < ls -t | head -n1 (*)

For such things you can use xargs:

ls -t | head -n1 | xargs grep "hello"

CodePudding user response:

You seem missunderstanding what subshell mean. As is a shell, every other biraries you run will implie a subprocess:

In

grep "Foo bar" $(/bin/ls -1t|head -n1)

You run two subcommands: ls | head, then retrieve answer to pass them as argument to a third subcommand: grep, you will run 3 subprocess.

You could avoid use of head by using read builtin:

read -r filename < <(/bin/ls -1t)
grep "Foo bar" "$filename"

As read read by line, only one line (the first) will be stored into filename variable. In this, only ls and grep will generate subprocess.

Note différence between $(...) and <(...), where first syntax will pass answer as content of string, but second argument will generate an unnamed fifo then pass the answer as input stream. Then note the redirection < and a space before <(...) telling read to take his input from the unnamed fifo.

Reversing order of a pipe chain could be usefull if you try to store his result into a variable:

head -n 1 < <(tac < <(grep 456 < <(seq {120,124}000)))
123456

seq {120,124}000 | grep 456 | tac | head -n1
123456

{ tac | head -n1 ;} < <(seq {120,124}000 | grep 456)
123456

And so on...

  • Related