2

What is the correct way to xargs to feed a list of strings as inputs to the middle of a command?

For example, say I want to move all files that come through a complicated series of "pipes" to the home directory. Something like

$ ... | ... | ... | awk '{print $2}' | xargs -L1 mv ~/

Tries to move the home directory to each input, rather than the desired order.

Someone previously asked a question about this, but the answers were not helpful:

Unix - "xargs" - output "in the middle" (not at the end!)

Is there a way to place the xargs input into a specific part of the command and not just at the end.

Community
  • 1
  • 1
jmlarson
  • 837
  • 8
  • 31
  • in the answers, they say: create an helper script. Have you tried that? – Jean-François Fabre Sep 16 '16 at 12:41
  • I can certainly make a helper script. But if I'm doing that, I don't really need xargs. I can just do everything within the script. `| xargs -L1 cmd` is very nice to **append** each line of input to some command, so I was hoping there was an easy way to **insert in a specific place** instead. – jmlarson Sep 16 '16 at 12:45

2 Answers2

2

Using GNU Parallel it looks like this:

$ ... | ... | ... | awk '{print $2}' | parallel mv {} ~/

It will run one job per file. Faster is:

$ ... | ... | ... | awk '{print $2}' | parallel -X mv {} ~/

It will insert multiple names before running the job.

Ole Tange
  • 31,768
  • 5
  • 86
  • 104
1

You didn't mention what xargs are you using.

If you use BSD xargs instead of GNU xargs, there is a powerful option -L that can do what you want:

     -J replstr
         If this option is specified, xargs will use the data read from
         standard input to replace the first occurrence of replstr instead
         of appending that data after all other arguments.  This option
         will not affect how many arguments will be read from input (-n),
         or the size of the command(s) xargs will generate (-s).  The op-
         tion just moves where those arguments will be placed in the com-
         mand(s) that are executed.  The replstr must show up as a dis-
         tinct argument to xargs.  It will not be recognized if, for in-
         stance, it is in the middle of a quoted string.  Furthermore,
         only the first occurrence of the replstr will be replaced.  For
         example, the following command will copy the list of files and
         directories which start with an uppercase letter in the current
         directory to destdir:

           /bin/ls -1d [A-Z]* | xargs -J % cp -Rp % destdir

Examples

$ seq 3 | xargs -J@ echo @ fourth fifth
1 2 3 fourth fifth
seq 3 | xargs -J@ ruby -e 'pp ARGV' @ fourth fifth
["1", "2", "3", "fourth", "fifth"]

The Ruby code pp ARGV here would pretty print the command arguments it receives. I usually use this way to debug xargs scripts.

Weihang Jian
  • 7,826
  • 4
  • 44
  • 55