8

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 ?

6
  • Not really a pipe but you might use ./bar <(./foo)
    – Lambert
    Oct 3, 2016 at 10:15
  • 2
    or ./bar < <(./foo) if bar is a script.
    – Lambert
    Oct 3, 2016 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 3, 2016 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 3, 2016 at 14:46
  • It takes you seconds to type Ctrl+A?
    – chepner
    Oct 4, 2016 at 0:10

3 Answers 3

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
2
  • 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.) Oct 3, 2016 at 15:03
  • You can do useful stuff like local IFS= inside a function, and calculate some variables based on the function args. Oct 3, 2016 at 15:05
4
./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.

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>

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.