Subject: Re: New xargs, was Re: upgrade to mv
To: NetBSD Userlevel Technical Discussion List <tech-userlevel@NetBSD.ORG>
From: Greg A. Woods <woods@weird.com>
List: tech-userlevel
Date: 08/16/2001 11:39:03
[ On Thursday, August 16, 2001 at 10:28:57 (-0500), Frederick Bruckman wrote: ]
> Subject: Re: New xargs, was Re: upgrade to mv
>
> As a matter of fact, the argument numbering has to start with "$0" for
> some reason that's a complete mystery to me...
>
> fredb@tautology-> echo foo bar | xargs -n2 sh -x -c 'echo $0 BLAH $1 BLAH'
> + echo foo BLAH bar BLAH
> foo BLAH bar BLAH
That's because of the somewhat bizzare way parameters are set from the
command-line for "sh -c" scripts. The first parameter is always used to
set $0, and the remainder are used for the rest of the positional
parameters.
This might help visualize what's going on a bit better:
$ echo foo bar | xargs -p sh -x -c 'echo 0:$0 1:$1'
sh -x -c echo 0:$0 1:$1 foo bar?...y
+ echo 0:foo 1:bar
0:foo 1:bar
I'm not sure why this isn't documented in our sh(1), but it is more or
less partly documented in our ksh(1) synopsis:
ksh [+-abCefhikmnprsuvxX] [+-o option] [ [ -c command-string [command-name] | -s | file ] [argument ...] ]
but not very well in the body of the manual:
0 The name the shell was invoked with (i.e.,
argv[0]), or the command-name if it was invoked
with the -c option and the command-name was sup-
plied, or the file argument, if it was supplied.
If the posix option is not set, $0 is the name of
the current function or script.
-c command-string
the shell executes the command(s) contained in com-
mand-string
Historically I don't remember what happened, though I suspect it's
"always been this way".
However all but one of the versions of the "real" Bourne Shell manuals I
can find are silent on what happens to additional parameters after the
'-c command-string'. That one which isn't silent is the Research UNIX
10'th Edition manual, which explicitly says they are ignored.
Both the early Korn Shell manuals (at least up to ksh88e or so) and the
book are similarly silent though one could construe the synopsis to say
that they are positional args (with the discovery that the first is $0
to be left as an exercise for the reader! ;-):
ksh [ +-aefhikmnprstuvx ] [ +-o option ] ... [ -c string ] [ arg . . . ]
By ksh88i though (the version included in Solaris-2.7), the manual
finally includes a full and proper explanation of what's going on:
-c Read commands from the command_string operand.
Set the value of special parameter 0 from the
value of the command_name operand and the posi-
tional parameters ($1, $2, and so on) in sequence
from the remaining arg operands. No commands will
be read from the standard input.
So, in other words what you really want is:
$ echo foo bar | xargs -p sh -x -c 'echo 0:$0 1:$1 2:$2' scriptname
sh -x -c echo 0:$0 1:$1 2:$2 scriptname foo bar?...y
+ echo 0:scriptname 1:foo 2:bar
0:scriptname 1:foo 2:bar
I note though that on Solaris 2.7 all the shells work the same:
$ echo foo bar | xargs /usr/5bin/sh -c 'echo 0:$0 1:$1 2:$2' scriptname
0:scriptname 1:foo 2:bar
$ echo foo bar | xargs /bin/sh -c 'echo 0:$0 1:$1 2:$2' scriptname
0:scriptname 1:foo 2:bar
$ echo foo bar | xargs /sbin/sh -c 'echo 0:$0 1:$1 2:$2' scriptname
0:scriptname 1:foo 2:bar
$ echo foo bar | xargs /bin/ksh -c 'echo 0:$0 1:$1 2:$2' scriptname
0:scriptname 1:foo 2:bar
$ Version M-11/16/88i
--
Greg A. Woods
+1 416 218-0098 VE3TCP <gwoods@acm.org> <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; Secrets of the Weird <woods@weird.com>