A better way of running commands - get stdout and stderr together, in order with timestamps, while easily running code as the command runs line-by-line.
Find a file
2025-01-16 18:26:55 -06:00
src write lines directly rather than using bash 2025-01-13 12:35:39 -06:00
.gitignore initial commit 2024-12-30 14:51:22 -06:00
Cargo.lock bump 2025-01-16 18:26:55 -06:00
Cargo.toml bump 2025-01-16 18:26:55 -06:00
README.md update docs and readme, bump 2025-01-12 18:13:03 -06:00

Better Commands

Crates.io Version docs.rs
This crate provides the ability to more easily run a [Command] while also doing something with its output as it runs, as well as providing some extra functionality.

Why?

Rust's stock [Command] kinda sucks, usually it only lets you get the output of a command with stdout and stderr completely separate. This crate lets you run code to handle the output as it prints, as well as providing all the lines together, with timestamps and which stream the line was printed to.

Features

  • Specifies whether a [Line] is printed to stderr or stderr
  • Provides a timestamp for each [Line]
  • Provides timestamps for the command as a whole (start, end, and duration)

A basic example (see [run]):

use better_commands::run;
use std::process::Command;

let output = run(Command::new("sleep").arg("1"));
println!("{:?}", output.duration());

A more complex example - this lets you provide a function to be run using the output from the command in real-time (see [run_funcs_with_lines]):

use better_commands::run_funcs_with_lines;
use better_commands::Line;
use std::process::Command;
let cmd = run_funcs_with_lines(&mut Command::new("echo").arg("hi"), {
    |stdout_lines| { // your function *must* return the lines
        let mut lines = Vec::new();
        for line in stdout_lines {
            lines.push(Line::from_stdout(line.unwrap()));
            /* send line to database */
            }
            return lines;
        }
    },
    {
    |stderr_lines| {
        // this code is for stderr and won't run because echo won't print anything to stderr, so we'll just put this placeholder here
        return Vec::new();
    }
});

// prints the following: [Line { printed_to: Stdout, time: Instant { tv_sec: 16316, tv_nsec: 283884648 }, content: "hi" }]
// (timestamp varies)
assert_eq!("hi", cmd.lines().unwrap()[0].content);