diff --git a/crates/pi-builtins/src/xargs.rs b/crates/pi-builtins/src/xargs.rs index ebd9c8d06..976dc7cba 100644 --- a/crates/pi-builtins/src/xargs.rs +++ b/crates/pi-builtins/src/xargs.rs @@ -741,7 +741,7 @@ fn process_input( return Ok(result); } - if !options.no_run_if_empty || have_pending_command { + if have_pending_command || (!options.no_run_if_empty && builder_options.replace.is_none()) { result.combine(current_builder.execute(host)?); } @@ -1468,6 +1468,12 @@ mod tests { assert_eq!(out, "\n"); } + #[test] + fn replace_mode_skips_empty_input_without_r() { + let result = run_simple(&["-I", "{}", "echo", "{}"], ""); + assert_eq!(result, (0, String::new(), String::new())); + } + #[test] fn verbose_echoes_command_line_to_stderr() { let (code, out, err) = run_simple(&["-t", "echo", "a"], "b\n"); diff --git a/packages/natives/CHANGELOG.md b/packages/natives/CHANGELOG.md index ed29a1901..f171b5206 100644 --- a/packages/natives/CHANGELOG.md +++ b/packages/natives/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed the native `xargs` builtin panicking in `-I`/`-i` replace mode when stdin is empty; it now exits successfully without running the command, matching GNU behavior ([#8595](https://github.com/can1357/oh-my-pi/issues/8595)). + ## [17.3.4] - 2026-08-14 ### Added