Andrew Mackenzie
Andrew Mackenzie

Reputation: 5737

How to send input to stdin of a process created with Command AND then capture output (and status)

I wish to create a child process using Command, feed it stdin from another child I create AND then wait for and capture output.

I have seen other questions and answers about one or the other, but not both.

The order I am trying is:

This last step doesn't compile as it says Child object is moved (consumed) when I get stdin for it.

Playground link

Upvotes: 4

Views: 2982

Answers (1)

user4815162342
user4815162342

Reputation: 154866

You need to take ownership of the dest_child.stdin pipe to give the object to BufWriter::new. Since the pipe is inside an Option, you can use Option::take to move it out without leaving dest_child "partially moved". Another issue with your code is that dest.stdin must be piped rather than inherited, otherwise dest_child.stdin will simply remain None. With those changes, your code compiles and runs (playground).

Note, however, that it is not necessary to manually transfer data from one process to another, the OS is perfectly capable of doing that on its own. For example (playground):

use std::process::{Command, Stdio};

fn main() {
    let mut dest = Command::new("wc")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();
    let _source = Command::new("ls")
        .stdout(dest.stdin.take().unwrap())
        .spawn()
        .unwrap();
    let dest_output = dest.wait_with_output().unwrap();

    match dest_output.status.code() {
        Some(0) => println!("OK: {}", String::from_utf8_lossy(&dest_output.stdout)),
        Some(code) => println!("Error {}", code),
        None => {}
    }
}

Upvotes: 5

Related Questions