9

This works perfectly :

./foo | ./bar

But I'd like something like that :

./bar <| ./foo

So I can pipe the other way around and change foo's arguments faster in command line.

The pipe needs to be realtime - my foo program does never return.

Is this possible ?

Bilow
  • 634
  • Not really a pipe but you might use ./bar <(./foo) – Lambert Oct 03 '16 at 10:15
  • 2
    or ./bar < <(./foo) if bar is a script. – Lambert Oct 03 '16 at 10:26
  • 5
    How would that be faster? Are you just looking for the shell shortcuts like Ctrl+A to go to the beginning and Alt+F to move forward one word at a time? – terdon Oct 03 '16 at 11:18
  • Yet shell shortcuts may be useful, I still have to press those key multiple times to get the cursor on the desired argument, whereas having the cursor directly at the end makes me win seconds – Bilow Oct 03 '16 at 14:46
  • It takes you seconds to type Ctrl+A? – chepner Oct 04 '16 at 00:10
  • Ctrl+A and Alt+F are faster than moving cursor to left. But it is even more faster to "up-arrow and edit". See Peter Cordes comments below. Thanks for suggestion though. – Bilow Oct 04 '16 at 09:04

3 Answers3

10

A simple and proper way can be to define a foobar function,

foobar () { ./foo "$@" | ./bar ; }

(either in the command line, as needed, or in some startup scripts, such as ".bashrc" for example). Then whenever you do :

foobar "this"  that   "and this also"

it will do

./foo  this   that   "and this also" | ./bar
  • 1
    Yup, I do this all the time to make it easy to up-arrow and edit the part of the command I want to change, without having to ctrl-left-arrow all the way to it. You can even leave the function definition as part of the command: foobar() { printf '%s\n' -x "$1" -y "$2" blah blah "${@:3}" | grep -v 123; }; foobar a b abc 'cd ef'. So you can easily tweak the function definition if you think of something else. ("${@:3}" expands to the positional parameters starting with 3, skipping the two we already used.) – Peter Cordes Oct 03 '16 at 15:03
  • You can do useful stuff like local IFS= inside a function, and calculate some variables based on the function args. – Peter Cordes Oct 03 '16 at 15:05
5
./bar < <( ./foo )

For example: cat < <(echo "hello there!")

To understand how it works, consider parts of the script separately.

This syntax: cat < /path/to/file will read the file /path/to/file and pipe it as stdin to cat.

This syntax: <(echo "hello there!") means to execute the command and attach the stdout to a file descriptor like /dev/fd/65. The result of the whole expression is a text like /dev/fd/65, and a command run in parallel and feeding that file descriptor.

Now, combined, the script will run the right command, pipe it to a file descriptor, convert that file descriptor to stdin for the left command, and execute the left command.

There is no overhead that I'd know of, it's exactly the same as a | b, just syntactic sugar.

VasyaNovikov
  • 1,246
4

I think you could do something like that with a named pipe:

mypipe=$(mktemp -d /tmp/XXXXXX)/pipe
mkfifo $mypipe
grep something < $mypipe & tail > $mypipe -f  some_input_file 
rm $mypipe

or put the unchanging part of the command in a shell script:

./foo "$@" | ./bar

and give the arguments to foo on the script command line:

./myscript <args to foo>
ilkkachu
  • 138,973