Skip to content
Open
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)
// 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
// 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