0

xargs -I not working for child command

Example:

# Not working
ls ....  | xargs -n 1 -I % sh -c  "cmd $(cmd2 % )"
# working
ls ....  | xargs -n 1 -I % sh -c  "cmd % "

Is there any solution for how to substitute inside child class?

Kusalananda
  • 333,661
JOEL
  • 1

1 Answers1

1

The issue is that the shell would expand the command substitution in the double-quoted string argument before xargs is even started, meaning the shell would run cmd2 with the literal argument % to calculate the last argument for xargs.

Your second example command does not have this issue as the shell code argument at the end does not contain any expansions that the calling shell would need to process before starting xargs.

You would solve this in the first command by simply single-quoting the argument instead of double-quoting it.

However, there are good reasons why parsing the output of ls is a bad idea. Since you embed the % placeholder in shell code that will be executed by sh -c, you would also have real issues if any filename contained quoting or globbing characters or expansions like $(...) or any other expansions. In this case, it would be safer to use an ordinary shell loop:

for name in ...; do cmd "$(cmd2 "$name")"; done

or, arguably more readable,

for name in ...; do
    cmd "$(cmd2 "$name")"
done

... where ... is a pattern that matches the names you are interested in.


See also:

Also related (embedding % in shell code with xargs has the same issues as embedding {} in shell code with find):

Kusalananda
  • 333,661