0

I want execute a command where I have the args as single string but they need to be in a custom position. E.g. in the following example I want the args to be positioned before any fixed args that I have written after the cp comamnd i.e. the path argument /somedir

I want:

echo -n 'file1 file2 file3' | xargs -d ' ' -I{} cp {} /somedir

to behave like:

cp file1 file2 file3 /somedir

but it doesn't...

It also looks like when including the -I{} option, the -d option makes xargs behave differently. It seems like it tries to pass each argument to a separate command call rather than all of them toa single one.

For example, this works:

echo -n 'file1 file2' | xargs -d' ' diff

But this fails

echo -n 'file1 file2' | xargs -d' ' -I{} diff {}

With error:

diff: missing operand after 'file1'
diff: Try 'diff --help' for more information.
diff: missing operand after 'file2'
diff: Try 'diff --help' for more information.

How can I get echo -n 'file1 file2 file3' | xargs -d ' ' -I{} cp {} /somedir to behave as intended

8
  • -I implies -x and -L 1. Is something like cp $(echo 'file1' 'file2' 'file3') somedir an option for you?
    – Walter A
    Commented Jul 6 at 12:46
  • @WalterA No. The args can be arbitrary, they are passed as a single string separated by spaces. Commented Jul 6 at 14:02
  • If this is specifically for the cp and mv commands, this is the reason for the -t option, which allows you to put the destination directory at the front.
    – Barmar
    Commented Jul 6 at 15:08
  • "I want execute a command where I have the args as single string" sounds like a variation of mywiki.wooledge.org/BashFAQ/050, if so the result would be fragile no matter how you try to implement it. Consider how you'd handle it if the args are file names and some of the file names contain spaces.
    – Ed Morton
    Commented Jul 6 at 16:15
  • When the args can be arbitrary, they are passed as a single string separated by spaces, you might use cp ${single_string} /somedir. When filenames with special characters are already embedded in single quotes, this should work.
    – Walter A
    Commented Jul 6 at 18:13

3 Answers 3

1

Like this:

$ echo -n 'file1 file2 file3' | xargs -d' ' bash -c 'echo cp "$@" /somedir' _arg0_
cp file1 file2 file3 /somedir

Not sure about your real use case but for the above example, the default xargs behavior would just work fine:

$ echo 'file1 file2 file3' | xargs bash -c 'echo cp "$@" /somedir' _arg0_
cp file1 file2 file3 /somedir
4
  • I want it to be split into 3 args. I used cp as an example. But I'm looking for it to work on any command, e.g. diff Commented Jul 6 at 13:59
  • ok. updated the answer.
    – pynexj
    Commented Jul 6 at 15:13
  • doesn't look like it works :( e.g. echo -n 'file1.txt file2.txt' | xargs -d' ' bash -c 'diff "$@"' produces error ``` diff: missing operand after 'file2.txt' diff: Try 'diff --help' for more information. ``` Commented Jul 7 at 4:52
  • @DavidNguyen format is bash -c cmd string arg1 arg2 ... . If you don't include string (_ in answer), arg1 gets eaten
    – jhnc
    Commented Jul 7 at 8:01
0

You can use an array for the args

read -a arg <<<"file1 file2 file3"
cp ${arg[@]} /some/dir
0

When you have the args as single string and separated with spaces, you don't need something special.
Examples:

single_string='file1 file2 file3'
cp ${single_string} /somedir

single_string='file1 file2'
diff ${single_string}

single_string='file_with_$_sign file[2]'
touch ${single_string}
ls -l ${single_string}
rm ${single_string}

Not the answer you're looking for? Browse other questions tagged or ask your own question.