#Need help converting shell commands to rust

12 messages · Page 1 of 1 (latest)

hardy palm
#

I am trying to convert one of my zsh function to rust and one of the command involves copy ip address of the machine to clipboard ipconfig getifaddr en0 | pbcopy How do I convert this to rust? I was trying something like this but doesn't seem to work. Also Is there any simpler way than using Command?

    Command::new("ipconfig")
        .arg("getifaddr")
        .arg("en0")
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output()
        .with_context(|| "error in ipconfig subprocess")?;

    Command::new("pbcopy")
        .stdin(Stdio::piped())
        .spawn()
        .with_context(|| "error in pbcopy subprocess")?;


hoary edge
#

In general, to replicate | in rust, you'd spawn the command, take its stdout, then spawn the other command (pbcopy), take its stdin, and std::io::copy them together.

hardy palm
#

Sorry, my bad. Updated the full code I was trying

#

Can you explain a bit more about std::io::copy them together part? Or any references would be helpful

hoary edge
#

It's a function that takes two arguments, a reader (the stdout) and a writer (the stdin). It repeatedly copies bytes from one into the other until the reader is empty.

#
let mut ipconfig = Command::new("ipconfig")
    .arg("getifaddr")
    .arg("en0")
    .stdout(Stdio::piped())
    .spawn()
    .with_context(|| "error in ipconfig subprocess")?;
let ipconfig_stdout = &mut ipconfig.stdout.take().unwrap();

let mut pbcopy = Command::new("pbcopy")
    .stdin(Stdio::piped())
    .spawn()
    .with_context(|| "error in pbcopy subprocess")?;
let pbcopy_stdin = &mut pbcopy.stdin.take().unwrap();

std::io::copy(ipconfig_stdout, pbcopy_stdin).with_context(|| "copying ipconfig to pbcopy")?;
proper turret
#

Though that takes a thread to do the copying. You could do what | in a shell actually does and make a pipe, i.e. use Stdio::piped() for the first command's stdout, and use the_first_command.stdout.take().unwrap() for the second command's stdin, e.g. ```rs
use std::process::{Command, Stdio};

fn main() {
let mut cmd1 = Command::new("cat")
.stdin(Stdio::inherit())
.stdout(Stdio::piped())
.spawn()
.unwrap();
let mut cmd2 = Command::new("cat")
.stdin(cmd1.stdout.take().unwrap())
.stdout(Stdio::inherit())
.spawn()
.unwrap();
cmd2.wait().unwrap();
cmd1.wait().unwrap();
}

hoary edge
#

oh right, that's better

hardy palm
#

Thanks

#

Just one question here. Why are we waiting for cmd2 before cmd1?

hoary edge
#

It doesn't really matter, they're both spawned. The wait just ensures your program doesn't continue until it's done.

#

You could (should?) also just status the second command.