Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/xargs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,13 @@ where
format!("Unterminated quote: {q}"),
));
}
if i == 0 {
// Input that consists only of delimiters (whitespace)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think it needs such a long comment

// produces no argument — a run of delimiters with no
// content between them yields nothing, matching GNU xargs.
// `i == 0` handles the case where we read no bytes at all;
// `result.is_empty()` additionally covers input we consumed
// but that was pure whitespace.
if result.is_empty() {
return Ok(None);
}
pending.clear();
Expand Down
44 changes: 44 additions & 0 deletions tests/test_xargs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,50 @@ fn xargs_if_empty() {
ucmd().args(&["--no-run-if-empty"]).succeeds().no_output();
}

#[test]
fn xargs_whitespace_only_input() {
// Input that consists only of delimiters (whitespace) produces no

@sylvestre sylvestre Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please make this comment shorter too

// argument, matching GNU xargs: a run of delimiters with no content
// between them yields no argument. The command still runs once with no
// extra args (the default, as with empty input).
ucmd().pipe_in(" ").succeeds().no_stderr().stdout_only("\n");

// Other ASCII whitespace should behave the same as a space.
ucmd()
.pipe_in("\t")
.succeeds()
.no_stderr()
.stdout_only("\n");
ucmd()
.pipe_in(" \t\n \n")
.succeeds()
.no_stderr()
.stdout_only("\n");

// With --no-run-if-empty, whitespace-only input means nothing to do.
ucmd()
.args(&["--no-run-if-empty"])
.pipe_in(" ")
.succeeds()
.no_output();

// The same holds when reading from a file with -a (issue #771 repro):
// the child must receive zero arguments, not an empty-string argument.
let temp_file = tempfile::NamedTempFile::new().unwrap();
std::fs::write(temp_file.path(), b" ").unwrap();
let result = ucmd()
.args(&[
"-a",
&temp_file.path().to_string_lossy(),
&path_to_testing_commandline(),
"-",
"--no_print_cwd",
])
.succeeds();
result.no_stderr();
assert_eq!(result.stdout_str(), "args=\n--no_print_cwd\n");
}

#[test]
fn xargs_replace_empty_input() {
ucmd()
Expand Down
Loading