Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 May 2001 18:03:19 -0700
From:      Dima Dorfman <dima@unixfreak.org>
To:        hackers@freebsd.org
Cc:        gad@freebsd.org
Subject:   xargs(1) "replstr" patch
Message-ID:  <20010512010319.B3B893E0B@bazooka.unixfreak.org>

next in thread | raw e-mail | index | archive | help
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
					dima@unixfreak.org

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 majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010512010319.B3B893E0B>