I was surprised when some command-line usage of xargs gave me trouble because it generated an empty argument. Further investigation shows that the BSD version of xargs (in net- and freebsd) splits the input in a very different way from everyone else, and it's also a bit inconsistent: Leading blanks, or any double blanks will make xargs generate empty arguments, but a trailing blank will not. I think it should be modified to be more like what everybody else does, and my expections were. At the very least the behaviour should be more consistent. The xargs specification is very loose and informal, but spec1170 says arguments should be 'separated by non-quoted blanks', which I read to support (or at least allow) my preferred behaviour. Even worse is that quoted empty strings will be treated the same way: A trailing "" string will be ignored. Fix: This is a simple patch to make xargs behave like I think it should. It is tested, but not very much. It should be noted that this patch has an analogous effect on leading and double NULLs in the -0 case. The -0 case can be argued both ways, I guess, but I haven't seen anything close to a spec for it, so I left it at this. How-To-Repeat: Run these commands (preferrably on different xargs implementations). cat > echoargs << 'eof' #!/bin/sh for x do echo "arg: '$x'"; done eof chmod +x echoargs echo xargs is: which xargs echo test leading, embedded double, and trailing space echo ' 1 2 3 ' | xargs ./echoargs echo test leading, embedded, and trailing quoted empty string echo '"" 2 "" 4 ""' | xargs ./echoargs
Linting my changes a bit more I found a stupid bug, sorry for that; fixed below. Type information for main added to quiet gcc warnings. -arnej --- xargs.c.orig Thu Feb 20 20:42:22 1997 +++ xargs.c Thu Feb 20 20:38:03 1997 @@ -61,6 +61,7 @@ void run __P((char **)); void usage __P((void)); +int main(argc, argv, env) int argc; char **argv, **env; @@ -89,7 +90,7 @@ /* 1 byte for each '\0' */ nline -= strlen(*ep++) + 1 + sizeof(*ep); } - nflag = xflag = 0; + nflag = xflag = wasquoted = 0; while ((ch = getopt(argc, argv, "0n:s:tx")) != EOF) switch(ch) { case 'n':
State Changed From-To: open->closed Patch applied. Thanks!