Command CLI

Библиотека позволяет запускать команды в ОС.

Варианты использования

  • spawn — runs the program and returns a value with details
  • output — runs the program and returns the output
  • status — runs the program and returns the exit code

Использование

Output - просто и быстро

    let output = Command::new("cat")
        .arg("/etc/issue")
        .output()
        .with_context(|| "ls command failed")?;

    println!("{}", output.status);
    println!("{}", String::from_utf8_lossy(&output.stdout));
    println!("{}", String::from_utf8_lossy(&output.stderr));

❗Ограничение - можно вызывать только существующие объекты, нельзя добавлять свой текст.

spawn - гибкий ввод

Самый гибкий вариант, позволяющий делать свой ввод, а не только существующие команды и файлы-папки, это через spawn:

    let mut child = Command::new("cat") // команда
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;

    let stdin = child.stdin.as_mut()?;
    stdin.write_all(b"Hello Rust!\n")?; // текст к команде, /n обязателен
    let output = child.wait_with_output()?;
    
    for i in output.stdout.iter() { // цикл на случай многострочного вывода
        print!("{}", *i as char);
    }
    Ok(())

❗Ограничение - можно подавать на вход текст лишь тем командам, которые требуют сразу указать вводный текст. При этом ряд команд делают паузу перед потреблением текста на вход, с такими свой ввод работать не будет это относится и к фильтрации через pipe = | grep <...> и аналоги.

Pipe (nightly) - полный ввод (не проверенный способ)

https://doc.rust-lang.org/std/pipe/fn.pipe.html Для использования нужен nightly вариант Rust

rustup install nightly
rustup default nightly

Использование:

#![feature(anonymous_pipe)] // только в Rust Nightly
use std::pipe

let text = "| grep file".as_bytes();

// Запускаем саму команду
let child = Command::new("ls")
    .arg("/Users/test")
    .stdin({
        // Нельзя отправить просто строку в команду
        // Нужно создать файловый дескриптор (как в обычном stdin "pipe")
        // Поэтому создаём пару pipes тут
        let (reader, mut writer) = std::pipe::pipe().unwrap();

        // Пишем строку в одну pipe
        writer.write_all(text).unwrap();

        // далее превращаем вторую для передачи в команду сразу при spawn. 
        Stdio::from(reader)
    })
    .spawn()?;