bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: specify a multiple of m arguments in xargs


From: Bernhard Voelker
Subject: Re: specify a multiple of m arguments in xargs
Date: Fri, 21 Feb 2020 09:00:42 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0

On 2020-02-20 20:46, Peng Yu wrote:
> Hi,
> 
> xargs by default does not put a multiple of m arguments (m is an
> integer greater than 1) to the command line. But is there a way that I
> can make sure only a multiple of m arguments are put the command line.

For my understanding: you have a program which would expect always
5 arguments from the initial input, right?

For this, the input has to be structured so that it is really a multiple
of M; otherwise, at least the last set of arguments is smaller than M.

> For example, for something like the following command, I'd like to
> make sure everytime there are 5 m arguments given to printf. But I
> don't think xargs can guarantee so by default in the output of the
> example.
> 
> $ seq 1000000 | xargs printf '%s\t%s\t%s\t%s\t%s\n' > /tmp/1.txt
> $ < /tmp/1.txt awk -v FS='\t' -e '!($1 && $2 && $3 && $4 && $5)'  | wc -l
> 105

In the above, xargs fills the command line for printf until the maximum
command line length limit for each printf invocation.  As it doesn't
know about the "multiple-to-M" rule, some of the lines in /tmp/1.txt
will just contain less than M elements.

What about using "xargs -n 5 ..."?

  $ seq 1000000 | xargs -n 5 > /tmp/1.txt
  $ < /tmp/1.txt awk -e '!($1 && $2 && $3 && $4 && $5)'  | wc -l
  0

Well, obviously, this will execute 'echo' many times, and therefore is
quite slow.  Therefore, as you know the input, you can make an assumption
of how many sets of M can be put into one command line.

With the example from 'seq', it seems to be safe to put 2000 sets of M=5
into one command line:

  $ seq 1000000 | xargs -n $(( 5 * 2000 )) printf '%s\t%s\t%s\t%s\t%s\n' > 
/tmp/1.txt
  $ < /tmp/1.txt awk -e '!($1 && $2 && $3 && $4 && $5)'  | wc -l
  0

Have a nice day,
Berny



reply via email to

[Prev in Thread] Current Thread [Next in Thread]