Normally xargs append the input arguments to the end of utility (plus fixed arguments). But sometimes you want put the input arguments in the middle or work around spaces inside arguments, then you may use '-I' or '-J'.
Before we get to that, let's review what xargs does under the hood.
xargs [-0opt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]
[-L number] [-n number [-x]] [-P maxjobs] [-s size]
[utility [argument ...]]
xargs breaks down the input into arguments delimited by spaces, tabs, newlines and EOF. It always does that. '-L' (based on number of line) and '-n' (based on how many arguments) controls when xargs should call the utility. xargs does NOT
do a second pass of shell parsing of the new arguments (Obviously it uses exec() facility).
In normal scenario, xargs put the extra arguments in the end. Each argument is considered as individual argument by the utility.
When using '-I %', any fixed argument which includes % is replaced by the new-arguments-string (Notice that all new arguments are concatenated together with a space between them), the replaced argument is considered as ONE argument
by the utility.
When using '-J %', any fixed argument which IS % (notice it is not match if it simply contains %) is EXPANDED with new arguments. Each new argument is considered as individual argument by the utility.
ls |xargs -L1 du -s
It won't work for filename with spaces (because xargs split them into separate arguments)
ls |xargs -L1 -I % du -s %
will work fine even for filename with spaces.