如何通过Rust中的stdin将输入发送到程序

时间:2014-02-06 22:12:29

标签: shell stdio rust

我试图在Rust中编写一个shell。 shell的一个功能是能够将输入重定向到文件,将文件重定向到输入,以及将程序的输出管道输出到另一个程序。我正在使用run::process_output中的std函数来运行程序并获取它们的输出,但是我不知道如何在运行之后将输入发送为程序员的stdin。有没有办法创建一个直接连接到run程序的对象,并像在stdin中输入一样输入输入?

3 个答案:

答案 0 :(得分:3)

此程序演示了如何启动外部程序并传输其标准输出 - > stdin在一起:

use std::io::{BufRead, BufReader, BufWriter, Write};
use std::process::{Command, Stdio};

fn main() {
    // Create some argument vectors for lanuching external programs
    let a = vec!["view", "-h", "file.bam"];
    let outsam = vec!["view", "-bh", "-o", "rust.bam", "-"];

    let mut child = Command::new("samtools")
        .args(&a)
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();
    let outchild = Command::new("samtools")
        .args(&outsam)
        .stdin(Stdio::piped())
        .spawn()
        .unwrap();

    // Create a handle and writer for the stdin of the second process
    let mut outstdin = outchild.stdin.unwrap();
    let mut writer = BufWriter::new(&mut outstdin);

    // Loop over the output from the first process
    if let Some(ref mut stdout) = child.stdout {
        for line in BufReader::new(stdout).lines() {

            let mut l: String = line.unwrap();
            // Need to add an end of line character back to the string
            let eol: &str = "\n";
            l = l + eol;

            // Print some select lines from the first child to stdin of second
            if (l.chars().skip(0).next().unwrap()) == '@' {
                // convert the string into bytes and write to second process
                let bytestring = l.as_bytes();
                writer.write_all(bytestring).unwrap();
            }
        }
    }
}

答案 1 :(得分:2)

您需要处理正在运行的进程才能执行此操作。

// spawn process
let mut p = std::process::Command::new(prog).arg(arg).spawn().unwrap();
// give that process some input, processes love input
p.stdin().get_mut_ref().write_str(contents);
// wait for it to complete, you may need to explicitly close stdin above
// i.e. p.stdin().get_mut_ref().close();
p.wait();

以上内容应该允许您向进程发送任意输入。如果生成的进程读取到eof,就像许多程序一样,关闭stdin管道是很重要的。

答案 2 :(得分:0)

迈克尔答案的更新版本。如果您的输出/输入很小,您可以将其读入一个字符串并以下列方式将其输回:

let output = Command::new("ls").arg("-aFl")
        .output().unwrap().stdout;
let output = String::from_utf8_lossy(&output);
println!("First program output: {:?}", output);
let put_command = Command::new("my_other_program")
        .stdin(Stdio::piped())
        .spawn().unwrap();
write!(put_command.stdin.unwrap(), "{}", output).unwrap();