Files
sausage/userland/findutils/src/xargs.rs
T
surma b9e3e3677d userland: search and exec tools, spawn library (T14)
rg (ripgrep 15.2), grep (ours, on ripgrep's regex crates), find and xargs
(ours), sed (uutils 0.3 wrapper), diff and cmp (uutils diffutils 0.6 with -r),
fd 10.5, jaq 2.3, env and timeout. userland/spawn is a small Command-like
client of the process interface. search-test.nu: 42 cases match native tools.
2026-11-06 17:21:51 +00:00

40 lines
1.8 KiB
Rust

//! Build sequential child commands from quoted or NUL-delimited input.
use std::io::{self, Read};
use sausage_spawn::{Command, Stdio};
fn run() -> Result<i32, Box<dyn std::error::Error>> {
let args: Vec<_> = std::env::args().skip(1).collect();
let mut i = 0;
let mut count = usize::MAX;
let mut null = false;
let mut no_empty = false;
while i < args.len() {
match args[i].as_str() {
"-0" => null = true,
"-r" => no_empty = true,
"-n" => { i += 1; count = args.get(i).ok_or("missing -n argument")?.parse()?; }
"--" => { i += 1; break; }
arg if arg.starts_with("-n") => count = arg[2..].parse()?,
arg if arg.starts_with('-') => return Err(format!("unsupported option: {arg}").into()),
_ => break,
}
i += 1;
}
if count == 0 { return Err("-n must be positive".into()); }
let argv = if i == args.len() { vec!["echo".into()] } else { args[i..].to_vec() };
let mut input = String::new(); io::stdin().read_to_string(&mut input)?;
let values = if null { input.split_terminator('\0').map(str::to_owned).collect() }
else { shlex::split(&input).ok_or("unmatched quote in input")? };
if values.is_empty() && no_empty { return Ok(0); }
let mut result = 0;
let batches = if values.is_empty() { vec![&[][..]] } else { values.chunks(count).collect() };
for batch in batches {
match Command::new(&argv[0]).args(&argv[1..]).args(batch).stdin(Stdio::Null).status() {
Ok(0) => (), Ok(255) => return Ok(124), Ok(_) => result = 123,
Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(127),
Err(_) => return Ok(126),
}
}
Ok(result)
}
fn main() { std::process::exit(match run() { Ok(code) => code, Err(e) => { eprintln!("xargs: {e}"); 1 } }); }