This threw me for a loop so I’m writing this down to help others (and likely me in the future). I swear I’ve used xargs with both -I and --max-args in the past but now I’m getting this warning and things are behaving improperly. It turns out there are two version of xargs, FreeBSD xargs and GNU xargs. FreeBSD xargs is installed on BSD systems (including MacOS) and GNU xargs is found on on Linux systems. This warning (and the incorrect result you also get) indicate you’re running GNU xargs.
xargs: warning: options --max-args and --replace/-I/-i are mutually exclusive, ignoring previous --max-args value
Note: This warning also occurs when using -n the shortcut version of --max-args.
How I Triggered the “--max-args and --replace/-I/-i are mutually exclusive” Warning
I ran a command that returned space separated content (e.g. echo '1 2 3 4') and I wanted to use xargs to:
- Run a separate command for each entry (
--max-args=1) - Put the entry in the middle of my command using
{}as a placeholder
(-I {} echo a-{}-b)
e.g.
echo '1 2 3 4' | xargs --max-args=1 -I {} echo a-{}-b
hoping to get the output
a-1-b
a-2-b
a-3-b
a-4-b
but instead I got the warning and a-1 2 3 4-b
Here is a run on GNU xargs
echo '1 2 3 4' | xargs --max-args=1 -I {} echo a-{}-b
xargs: warning: options --max-args and --replace/-I/-i are mutually exclusive, ignoring previous --max-args value
a-1 2 3 4-b
(but FreeBSD xargs does give the desired output).
Solution for GNU xargs
The solution I found requires two things:
- Switching the order of
--max-args=1and-I {}, so-I {}comes first - And adding
| tr " " "\n"before| xargs ...to convert (a.k.a. to TRanslate) a space" "into a new line\n
This updated version works properly on GNU xargs (and FreeBSD xargs)
$ echo '1 2 3 4' | tr " " "\n" | xargs -I {} --max-args=1 echo a-{}-b
a-1-b
a-2-b
a-3-b
a-4-b
Is There a Better Way to Do This?
Using both --max-args=1 and -I {} seems like a pretty common use case, is there a better way to do this?
Leave a Reply