]> err.no Git - moreutils/commitdiff
support -n option
authorPierre Habouzit <madcoder@debian.org>
Wed, 22 Jul 2009 09:17:20 +0000 (11:17 +0200)
committerJoey Hess <joey@gnu.kitenet.net>
Sat, 25 Jul 2009 07:59:37 +0000 (09:59 +0200)
This makes parallel stuff more than one argument to the subcommands.
It's very useful when subcommands are slow to start and are able to
process multiple files at once, that tasks are small but plenty.

For example:
    $ ./parallel -n 3 echo -- a b c d e f g h
    a b c
    d e f
    g h

Signed-off-by: Pierre Habouzit <madcoder@debian.org>
parallel.c
parallel.docbook

index 8045e2209d05f17d220735ab57a8f1742ae2c0d3..99a9727e0937adc456063826d1caeb581e23bd7d 100644 (file)
@@ -38,7 +38,7 @@ void usage() {
        exit(1);
 }
 
-void exec_child(char **command, char *argument, int replace_cb) {
+void exec_child(char **command, char **arguments, int replace_cb, int nargs) {
        char **argv;
        int argc = 0;
        int i;
@@ -48,14 +48,14 @@ void exec_child(char **command, char *argument, int replace_cb) {
        }
        if (replace_cb == 0)
                argc++;
-       argv = calloc(sizeof(char*), argc+1);
+       argv = calloc(sizeof(char*), argc + nargs);
        for (i = 0; i < argc; i++) {
                argv[i] = command[i];
                if (replace_cb && (strcmp(argv[i], "{}") == 0))
-                       argv[i] = argument;
+                       argv[i] = arguments[0];
        }
        if (replace_cb == 0)
-               argv[i-1] = argument;
+               memcpy(argv + i - 1, arguments, nargs * sizeof(char *));
        if (fork() == 0) {
                /* Child */
                execvp(argv[0], argv);
@@ -81,16 +81,18 @@ int main(int argc, char **argv) {
        int maxjobs = -1;
        int curjobs = 0;
        int maxload = -1;
+       int argsatonce = 1;
        int opt;
        char **command = calloc(sizeof(char*), argc);
        char **arguments = NULL;
        int argidx = 0;
+       int arglen = 0;
        int cidx = 0;
        int returncode = 0;
        int replace_cb = 0;
        char *t;
 
-       while ((opt = getopt(argc, argv, "+hij:l:")) != -1) {
+       while ((opt = getopt(argc, argv, "+hij:l:n:")) != -1) {
                switch (opt) {
                case 'h':
                        usage();
@@ -116,12 +118,26 @@ int main(int argc, char **argv) {
                                exit(2);
                        }
                        break;
+               case 'n':
+                       errno = 0;
+                       argsatonce = strtoul(optarg, &t, 0);
+                       if (errno != 0 || argsatonce < 1 || (t-optarg) != strlen(optarg)) {
+                               fprintf(stderr, "option '%s' is not a positive number\n",
+                                       optarg);
+                               exit(2);
+                       }
+                       break;
                default: /* ’?’ */
                        usage();
                        break;
                }
        }
 
+       if (replace_cb && argsatonce > 1) {
+               fprintf(stderr, "options -i and -n are incomaptible\n");
+               exit(2);
+       }
+
        if (maxjobs < 0) {
 #ifdef _SC_NPROCESSORS_ONLN
                maxjobs = sysconf(_SC_NPROCESSORS_ONLN);
@@ -134,18 +150,15 @@ int main(int argc, char **argv) {
        while (optind < argc) {
                if (strcmp(argv[optind], "--") == 0) {
                        int i;
-                       size_t mem = (sizeof (char*)) * (argc - optind);
 
-                       arguments = malloc(mem);
+                       optind++;
+                       arglen = argc - optind;
+                       arguments = calloc(sizeof(char *), arglen);
                        if (! arguments) {
                                exit(1);
                        }
-                       memset(arguments, 0, mem);
-                       optind++; /* Skip the -- separator, skip after
-                                  * malloc so we have a trailing
-                                  * null */
 
-                       for (i = 0; i < argc - optind; i++) {
+                       for (i = 0; i < arglen; i++) {
                                arguments[i] = strdup(argv[optind + i]);
                        }
                        optind += i;
@@ -157,15 +170,18 @@ int main(int argc, char **argv) {
                optind++;
        }
 
-       while (arguments[argidx] != 0) {
+       while (argidx < arglen) {
                double load;
 
                getloadavg(&load, 1);
 
                if ((maxjobs > 0 && curjobs < maxjobs) ||
                    (maxload > 0 && load < maxload)) {
-                       exec_child(command, arguments[argidx], replace_cb);
-                       argidx++;
+                       if (argsatonce > arglen - argidx)
+                               argsatonce = arglen - argidx;
+                       exec_child(command, arguments + argidx,
+                                  replace_cb, argsatonce);
+                       argidx += argsatonce;
                        curjobs++;
                }
 
index 2fa5a5c78099fa77afe2e3448cb6a93cb72ed24c..6da57bb56882d42289b36efe8a11b544be98b9c3 100644 (file)
@@ -84,6 +84,14 @@ Written by Joey Hess
                        </listitem>
                </varlistentry>
                
+               <varlistentry>
+                       <term><option>-n</option></term>
+                       <listitem>
+                               <para>Number of arguments to pass to one command at
+                                  once. Incompatible with -i</para>
+                       </listitem>
+               </varlistentry>
+               
                </variablelist>
                
        </refsect1>