Passing multiple parameters via xargs
I’d like to be able to use xargs
to execute multiple parameters in different parts of a command.
For example, the following:
echo {1..8} | xargs -n2 | xargs -I v1 -I v2 echo the number v1 comes before v2
I would hope that it would return
the number 1 comes before 2
the number 3 comes before 4
… etc
Is this achievable? I suspect that my multiple use of -I
is incorrect.
I believe that you can’t use -I
that way.
But you can get the effect / behavior you want by saying:
echo {1..8} | xargs -n2 sh -c 'echo "the number $1 comes before $2"' sh
This, essentially, creates an ad hoc one-line shell script,
which xargs
executes via sh -c
.
The two values that xargs
parses out of the input
are passed to this “script”.
The shell then assigns those values to $1
and $2
,
which you can then reference in the “script”.
try this:
echo {1..8} |xargs -n 2 bash -c 'echo "the number $0 comes before $1"'
In the specific case of printf
, you could always do:
echo {1..8} | xargs printf 'the number %s comes before %sn'
because printf
has an intrinsic xargs
-like ability to execute multiple times
if it is given more arguments than it needs for a single invocation.
Though that has little advantage over
printf 'the number %s comes before %sn' {1..8}
And for large lists, the simple xargs
command could result
in xargs
running several instances of printf
,
some of which might have odd numbers of arguments.
You could pass -n 1000
to xargs
to guard against that, where 1000 is an even number that should be small enough so as not to reach the arg list too long limit and large enough to avoid running so many printf
s.
Note that xargs
would call, not your shell’s builtin printf
,
but the external printf
, with each invocation in a separate new process.
Also note that for an empty input, except on some BSDs, it would still run printf
once with no argument. GNU xargs
and compatible have a -r
(or --no-run-if-empty
) option to avoid that.
To be clear, this simple answer is specific to your printf
example,
and would not work in the general case
where you must pass two parameters at a time to your command
(as would be the case for diff
, for example).
To solve the general problem with zsh
, you can use:
for i j ({1..8}) echo "the number $i comes before $j"