Folks,

The attached patch adds a "replacement string" feature to xargs(1).
There's a full description in the man page update (also attached), but
the following should demonstrate the new functionality:

        dima@spike% ./xargs -J [] echo CMD LINE [] ARGS < test
        CMD LINE this is the contents of the test file ARGS
        dima@spike% ./xargs -J [] echo CMD [] LINE ARGS < test
        CMD this is the contents of the test file LINE ARGS
        dima@spike% ./xargs -J [] echo [] CMD LINE ARGS < test
        this is the contents of the test file CMD LINE ARGS

This is similar to, but not identical to, the -I option described in
SUSv2.  The latter allows the replstr ("[]" above) to be attached to
other arguments, and appear multiple times.  Furthermore, it implies
'-n 1'.  Although the features are similar, they can solve different
problems; even if -I is implemented later, this (-J) would still be
useful.  -J also doesn't have the performance implications attached
with -I.

There was a nice, long thread about this on current a few weeks ago
(topic: "Re: cp -d dir patch for review (or 'xargs'?)").  It was
rather inconclusive, but nobody managed to come up with a way to
*properly* and *easily* imitate this functionality.  Writing a script
to do this *properly* (i.e., handle environment growth) isn't as easy
as it sounds (although it's possible, of course).

The patch is a joint effort between myself and Garance Dorsihn (gad).

Comments?  Suggestions?

Thanks in advance,

                                        Dima Dorfman
                                        [EMAIL PROTECTED]

Index: xargs.1
===================================================================
RCS file: /st/src/FreeBSD/src/usr.bin/xargs/xargs.1,v
retrieving revision 1.13
diff -u -r1.13 xargs.1
--- xargs.1     2001/05/02 06:41:46     1.13
+++ xargs.1     2001/05/11 23:57:27
@@ -36,7 +36,7 @@
 .\"    @(#)xargs.1     8.1 (Berkeley) 6/6/93
 .\" $FreeBSD: src/usr.bin/xargs/xargs.1,v 1.13 2001/05/02 06:41:46 dd Exp $
 .\"
-.Dd June 6, 1993
+.Dd May 7, 2001
 .Dt XARGS 1
 .Os
 .Sh NAME
@@ -45,6 +45,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl 0
+.Op Fl J Ar replstr
 .Oo
 .Fl n Ar number
 .Op Fl x
@@ -91,6 +92,38 @@
 .Fl print0
 function in
 .Xr find 1 .
+.It Fl J Ar replstr
+If this option is specified,
+.Nm
+will use the data read from standard input to replace the first occurrence of
+.Ar replstr
+instead of appending that data after all other arguments.
+This option will not effect how many arguments will be read from input
+.Pq Fl n ,
+or the size of the command(s)
+.Nm
+will generate
+.Pq Fl s .
+The option just moves where those arguments will be placed in the command(s)
+that are executed.
+The
+.Ar replstr
+must show up as a distinct
+.Ar argument
+to
+.Nm .
+It will not be recognized if, for instance, it is in the middle of a
+quoted string.
+Furthermore, only the first occurrence of the
+.Ar replstr
+will be replaced.
+For example, the following command will copy the list of files and
+directories which start with an uppercase letter in the current
+directory to
+.Pa destdir :
+.Pp
+.Dl /bin/ls -1d [A-Z]* | xargs -J [] cp -rp [] destdir
+.Pp
 .It Fl n Ar number
 Set the maximum number of arguments taken from standard input for each
 invocation of the utility.
@@ -173,6 +206,11 @@
 utility is expected to be
 .St -p1003.2
 compliant.
+The
+.Fl J
+option is a non-standard
+.Fx
+extention which may not be available on other operating systems.
 .Sh BUGS
 If
 .Ar utility
Index: xargs.c
===================================================================
RCS file: /st/src/FreeBSD/src/usr.bin/xargs/xargs.c,v
retrieving revision 1.9
diff -u -r1.9 xargs.c
--- xargs.c     1999/08/28 01:07:50     1.9
+++ xargs.c     2001/05/11 23:57:27
@@ -70,10 +70,15 @@
 {
        register int ch;
        register char *p, *bbp, *ebp, **bxp, **exp, **xp;
-       int cnt, indouble, insingle, nargs, nflag, nline, xflag, wasquoted;
-       char **av, *argp, **ep = env;
+       int cnt, jfound, indouble, insingle;
+       int nargs, nflag, nline, xflag, wasquoted;
+       char **av, **avj, *argp, **ep, *replstr;
        long arg_max;
 
+       ep = env;
+       jfound = 0;
+       replstr = NULL;                 /* set if user requests -J */
+
        /*
         * POSIX.2 limits the exec line length to ARG_MAX - 2K.  Running that
         * caused some E2BIG errors, so it was changed to ARG_MAX - 4K.  Given
@@ -96,8 +101,11 @@
                nline -= strlen(*ep++) + 1 + sizeof(*ep);
        }
        nflag = xflag = wasquoted = 0;
-       while ((ch = getopt(argc, argv, "0n:s:tx")) != -1)
+       while ((ch = getopt(argc, argv, "0J:n:s:tx")) != -1)
                switch(ch) {
+               case 'J':
+                       replstr = optarg;
+                       break;
                case 'n':
                        nflag = 1;
                        if ((nargs = atoi(optarg)) <= 0)
@@ -144,6 +152,13 @@
        else {
                cnt = 0;
                do {
+                       if (replstr && strcmp(*argv, replstr) == 0) {
+                               jfound = 1;
+                               argv++;
+                               for (avj = argv; *avj; avj++)
+                                       cnt += strlen(*avj) + 1;
+                               break;
+                       }
                        cnt += strlen(*bxp++ = *argv) + 1;
                } while (*++argv);
        }
@@ -211,6 +226,10 @@
                        if (xp == exp || p > ebp || ch == EOF) {
                                if (xflag && xp != exp && p > ebp)
                                        errx(1, "insufficient space for arguments");
+                               if (jfound) {
+                                       for (avj = argv; *avj; avj++)
+                                               *xp++ = *avj;
+                               }
                                *xp = NULL;
                                run(av);
                                if (ch == EOF)
@@ -253,6 +272,10 @@
                        if (xflag)
                                errx(1, "insufficient space for arguments");
 
+                       if (jfound) {
+                               for (avj = argv; *avj; avj++)
+                                       *xp++ = *avj;
+                       }
                        *xp = NULL;
                        run(av);
                        xp = bxp;
@@ -307,7 +330,8 @@
 static void
 usage()
 {
-       (void)fprintf(stderr,
-"usage: xargs [-0] [-t] [-n number [-x]] [-s size] [utility [argument ...]]\n");
+       fprintf(stderr,
+           "usage: xargs [-0t] [-J replstr] [-n number [-x]] [-s size]\n"
+           "           [utility [argument ...]]\n");
        exit(1);
 }

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to