Command în Rust

Pornește alt program (proces copil): new() alege programul, arg() și args() adaugă argumente.

Sintaxă
use std::process::Command;

Command::new("program")
    .arg("un argument")
    .args(["altul", "încă unul"])
    .output() / .status() / .spawn()

Ce face Command

Command::new("ls") pregătește pornirea unui program extern. Programul este căutat în PATH, ca în terminal. Cu .arg(x) adaugi un argument, cu .args([..]) mai multe. Alte setări: .current_dir(d) (directorul de lucru), .env(k, v) (o variabilă de mediu), .stdin()/.stdout()/.stderr().

Pornirea propriu-zisă se face cu una dintre trei metode: output() rulează și strânge tot ce scrie programul, status() rulează și lasă programul să scrie direct pe ecran, spawn() pornește programul și returnează imediat, fără să aștepte.

Argumentele sunt transmise exact cum le dai, fără shell: .arg("a b") este un singur argument cu spațiu, iar *, | sau > nu au sens special. Dacă ai nevoie de shell, pornește-l explicit: Command::new("sh").args(["-c", "..."]).

Parametri

Parametru Descriere
program La new: numele sau calea programului.
arg / args Un argument, respectiv o listă de argumente.

Ce returnează

new, arg și args returnează comanda (pentru înlănțuire); pornirea dă io::Result.

Exemple

Exemplul 1: Pornirea lui echo cu argumente

Al doilea apel arată că un argument cu spațiu rămâne un singur argument.

use std::process::Command;

fn main() -> std::io::Result<()> {
    let iesire = Command::new("echo").arg("Salut").arg("din Iași").output()?;
    print!("{}", String::from_utf8_lossy(&iesire.stdout));

    let iesire = Command::new("sh")
        .args(["-c", "echo \"număr de argumente: $#, primul: $1\"", "sh", "un singur argument"])
        .output()?;
    print!("{}", String::from_utf8_lossy(&iesire.stdout));
    Ok(())
}

Rezultat

Salut din Iași
număr de argumente: 1, primul: un singur argument

Exemplul 2: Director de lucru și variabile de mediu

use std::fs;
use std::process::Command;

fn main() -> std::io::Result<()> {
    fs::create_dir_all("poze")?;
    for nume in ["vara.jpg", "iarna.jpg", "munte.png"] {
        fs::write(format!("poze/{nume}"), "")?;
    }

    let lista = Command::new("ls").current_dir("poze").output()?;
    print!("{}", String::from_utf8_lossy(&lista.stdout));

    let salut = Command::new("sh").args(["-c", "echo \"Bun venit, $NUME!\""]).env("NUME", "Ioana").output()?;
    print!("{}", String::from_utf8_lossy(&salut.stdout));
    Ok(())
}

Rezultat

iarna.jpg
munte.png
vara.jpg
Bun venit, Ioana!

Exemplul 3: Program inexistent

Dacă programul nu este găsit, pornirea dă Err cu tipul NotFound.

use std::process::Command;

fn main() {
    match Command::new("program-care-nu-exista").output() {
        Ok(_) => println!("pornit"),
        Err(e) => println!("nu pot porni programul: {e} ({:?})", e.kind()),
    }
}

Rezultat

nu pot porni programul: No such file or directory (os error 2) (NotFound)

Greșeli frecvente

  • Scrii toată linia într-un singur new: Command::new("ls -l") caută un program numit ls -l. Pune argumentele cu arg.
  • Construiești comanda sh -c din date de la utilizator: cineva poate injecta alte comenzi. Transmite datele ca argumente separate.
  • Folosești comenzi care există doar pe Linux/macOS (ls, sh) într-un program care trebuie să meargă și pe Windows.

Comenzi înrudite

  • Command::output: Rulează programul, așteaptă să termine și returnează codul de ieșire și tot ce a scris pe stdout și stderr.
  • Command::status: Rulează programul, îl lasă să scrie direct în terminal și returnează doar felul în care s-a terminat.
  • Command::spawn: Pornește programul și returnează imediat un Child, fără să aștepte; poți comunica cu el și îl aștepți mai târziu.
  • env::var: Citește valoarea unei variabile de mediu (HOME, PATH, setări proprii); dă Err dacă nu există.