Skip to content

Commit

Permalink
xargs exits on empty line from stdin (#435)
Browse files Browse the repository at this point in the history
* BSD versions of xargs don't support the -l option
* Standards document for xargs mentions -L but not -l [1]
* Follow GNU version and accept -l as an alias for -L, but list standard -L in usage string
* Behaviour of -L/-l didn't match xargs on my linux system: input loop was terminated on
  first empty line of STDIN
* Skipping empty lines makes the behaviour match GNU version

1. https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/xargs.html

%cat -n in # not all lines have content
     1	#!/usr/bin/perl
     2	
     3	=begin metadata
     4	
     5	Name: awk
     6	Description: pattern-directed scanning and processing language
     7	Author: Tom Christiansen, tchrist@perl.com
     8	Author: Larry Wall, larry@wall.org
     9	License: perl
    10	

%xargs -L 1 < in # implicit 'echo' for each line of stdin
#!/usr/bin/perl
=begin metadata
Name: awk
Description: pattern-directed scanning and processing language
Author: Tom Christiansen, tchrist@perl.com
Author: Larry Wall, larry@wall.org
License: perl

%perl xargs -L 1 < in # patched version
#!/usr/bin/perl
=begin metadata
Name: awk
Description: pattern-directed scanning and processing language
Author: Tom Christiansen, tchrist@perl.com
Author: Larry Wall, larry@wall.org
License: perl
  • Loading branch information
mknos authored Jan 31, 2024
1 parent 2f0ea85 commit ca9a191
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions bin/xargs
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,20 @@ use constant EX_FAILURE => 1;
my $Program = basename($0);

my %o;
getopts('0tn:l:s:I:', \%o) or die <<USAGE;
getopts('0tn:L:l:s:I:', \%o) or die <<USAGE;
Usage:
$Program [-0t] [-n num] [-l num] [-s size] [-I repl] prog [args]
$Program [-0t] [-n num] [-L num] [-s size] [-I repl] prog [args]
-0 expect NUL characters as separators instead of spaces
-t trace execution (prints commands to STDERR)
-n num pass at most 'num' arguments in each invocation of 'prog'
-l num pass at most 'num' lines of STDIN as 'args' in each invocation
-L num pass at most 'num' lines of STDIN as 'args' in each invocation
-s size pass 'args' amounting at most to 'size' bytes in each invocation
-I repl for each line in STDIN, replace all 'repl' strings in 'args'
before execution
USAGE

for my $opt (qw( l n s )) {
for my $opt (qw( L l n s )) {
next unless (defined $o{$opt});
if (!length($o{$opt}) || $o{$opt} =~ m/\D/) {
warn "$Program: option $opt: invalid number '$o{$opt}'\n";
Expand All @@ -53,7 +53,7 @@ for my $opt (qw( l n s )) {
exit EX_FAILURE;
}
}

$o{'L'} = $o{'l'} if defined $o{'l'};
my @args = ();

$o{I} ||= '{}' if exists $o{I};
Expand All @@ -65,13 +65,14 @@ while (1) {
my $totlines = 0;
while (<STDIN>) {
chomp;
next unless (length && m/\S/);
$line .= $_ if $o{I};
$totlines++;
my @words = quotewords($sep, 1, $_);
push @args, grep { defined } @words;
last if $o{n} and @args >= $o{n};
last if $o{s} and length("@args") >= $o{s};
last if $o{l} and $totlines >= $o{l};
last if $o{'L'} and $totlines >= $o{'L'};
}
my @run = @ARGV;
push @run, 'echo' unless (@run);
Expand Down

0 comments on commit ca9a191

Please sign in to comment.