17

I'm trying to run an app (let's say top) so it will read from a file for stdin and write to another file from stdout.

Currently I have

mkfifo stdin.pipe
(tail -f stdin.pipe) | top

which works as expected, as I can then echo something to that file and top will receive it. But I'm unable to redirect the output of top. How can I achieve this?

EDIT:

Ok, let's scratch top. I'm testing with this:

cat test.sh

echo Say something
read something
echo you said $something
2
  • Are you sure top reads from stdin? Mine doesn't. You can redirect output from top using the -b (batch) option: top -n 1 -b > gash Commented Mar 28, 2013 at 11:35
  • @cdarke I'm sorry, you're right. I was making tests with another app. top doesn't work the same way. Is there a way I can map stdin and stdout to files and use them to control a cli app? Commented Mar 28, 2013 at 11:38

2 Answers 2

54

Let's forget about top, that appears to be a red herring.

To map stdin or stdout to files, you can use redirection:

some_program < input_file          # Redirects stdin

another_program > output_file      # Redirects stdout

or even:

yet_another  < input_file > output_file
Sign up to request clarification or add additional context in comments.

6 Comments

Is this async or sync? I just tested it with a 2 lines bash that will say "Hi", wait for input and then say "Bye". I was able to see the output in the output_file after I redirected something to the input_file (aka, when the app finished running)
If you are commuicating between programs then use an anonymous pipe, it will be more efficient than using a temporary file. Depends what you mean by sync/async in this context, but all shell IO is buffered. The buffer is flushed and the file is closed after each redirection, but you can get issues if a program is reading while one is writing (to a file, not a pipe).
The problem is that I'm trying to control a CLI app from PHP so I can't save the handle to the pipe, that's why I need to be able to read/write to/from files. How can I force output to be flushed instead of going to buffer?
Use a named pipe instead of a file, you can redirect to a named pipe just as if it was a file (um, actually, it is a file). You can also read a named pipe from PHP just as if it was a text file.
are you sure that this will work with the example script I posted in my question? (the edit part). I just created mkfifo in and out and I ran my script. I expected to get Say something after cat out but I didn't get anything.
|
8

Is there a way I can map stdin and stdout to files and use them to control a cli app?

It sounds like you are looking for coprocesses, added to Bash in 4.0.

coproc cat                    # Start cat in background
echo Hello >&${COPROC[1]}     # Say "Hello" to cat
read LINE <&${COPROC[0]}      # Read response
echo $LINE                    # cat replied "Hello"!

Before 4.0 you had to use two named pipes to achieve this.

1 Comment

Interesting addition!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.