5

By default xargs will concatenate many lines of its input and pass then to the specified command. For example:

echo -e 'line 1\nline 2\nline 3' | xargs echo 

results in

line 1 line 2 line 3

Since the arguments are sent to a single echo command (within the limits of the command line length).

Sometimes you want to use replacement string to put the arguments somewhere else in the command, rather than the end:

echo -e 'line 1\nline 2\nline 3' | xargs -Ix echo x DONE
line 1 DONE
line 2 DONE
line 3 DONE

Now, xargs only substituted one argument per each echo invocation, because as the man page says "-I implies -L 1...". That's probably the right behavior for a typical case, but is there any way to override it, so I get line 1 line 2 line 3 DONE as the output?

Please note that my example is illustrative only - I'm not very interested in non-xargs ways of tacking this issue.

4 Answers 4

4

I don't know of an xargs option which will do that, but you can achieve something similar with an invocation of bash -c:

$ echo -e "line 1\nline    2\nline 3" | xargs bash -c 'echo "${@}" DONE' _
line 1 line 2 line 3 DONE

Note that xargs does not provide the lines as arguments, even if you specify -L. You might want to use -d to specify that new-line separates items (gnu xargs only, I believe). Contrast the following:

$ echo -e "line 1\nline    2\nline 3" |
  xargs bash -c 'printf "<%s>\n" "${@}" DONE' _
<line>
<1>
<line>
<2>
<line>
<3>
<DONE>

$ echo -e "line 1\nline    2\nline 3" |
  xargs -d\\n bash -c 'printf "<%s>\n" "${@}" DONE' _
<line 1>
<line    2>
<line 3>
<DONE>
4
  • Good point about how xargs is breaking up args, on whitespace boundaries, not line boundaries (although lines are special for arguments like -L and hence implicitly for -I).
    – BeeOnRope
    Jan 23, 2014 at 3:42
  • @BeeOnRope: even with -L, xargs breaks arguments on wordspace. The line count specifies the number of lines containing arguments but the lines are not otherwise treated specially.
    – rici
    Jan 23, 2014 at 17:29
  • Right, that's why I said "lines are special" not that xargs changes the way it breaks up arguments, but that it does use lines to initially chunk the input into invocations, then proceeds to break up on whitespace as usual.
    – BeeOnRope
    Jan 23, 2014 at 19:34
  • 1
    echo -e "line 1\nline 2\nline 3" | parallel echo :{}:
    – Ole Tange
    Jan 24, 2014 at 8:06
2

Convert newlines into \nul terminators, then use xargs -0

$ echo -ne 'line 1\nline 2\nline 3\n' | tr '\n' '\0' | xargs -0 -Ix echo x DONE
line 1 DONE
line 2 DONE
line 3 DONE
1
  • 3
    As above, I got the same output already without the tr and -0 (it is not needed here). The issue is that I want it all on one line: line 1 DONE line 2 DONE ...
    – BeeOnRope
    Jan 25, 2014 at 1:38
0

How about this one:

arg=$( echo -e 'line 1\nline 2\nline 3' | xargs )
echo $arg Done.

I used this construct to generate a multiple page PDF-file from many single PDFs:

arg=$( find -mmin -60 -type f -name "*.pdf" | xargs )
pdftk $arg cat output AllMyRecentPDFs.pdf
1
  • 1
    The question is about using xargs to that effect.
    – RalfFriedl
    Oct 26, 2019 at 14:01
-1

If I understand your question, I think you just want to convert newlines to a non-delimiter.

echo -ne 'foo\nbar\nbaz' | tr '\n' ' ' | xargs -I{} echo {} DONE

4
  • No, I want each of foo, bar and baz to be unique arguments. The example is artificial - the point is to be able to put something after the arguments added by xargs.
    – BeeOnRope
    Jul 15, 2015 at 23:23
  • That's what you'll get. For example, ls | tr '\n' ' ' | xargs -I{} echo {} DONE yields dir1/ dir2/ dir3/ DONE. Jul 17, 2015 at 17:06
  • No, in that case the entire string "dir1/ dir2/ dir3/" is passed as a single argument to echo, which is not what I want. Yes the output is the same in my toy example, but in real life I'm not passing to echo. Try your example but passing it to a version of echo that quotes all the arguments (for example) and you'll see the difference.
    – BeeOnRope
    Jul 17, 2015 at 17:56
  • Then what you want can't be done just with xargs options, I don't think. (Also, though I see what you mean now, it's very unclear that this is what you intend from your original post, given the example you include). Jul 22, 2015 at 1:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .