Why does ''xargs bash -vc "$(declare -f {})"'' not work?

62 Views Asked by At

Bash 3.2.57 running on OSX.

  1. Following displays the function definition as expected.
declare -f my_bash_function
  1. Following works as well but only with -v flag.
bash -vc "$(declare -f my_bash_function)"
  1. Following does not work as I would expect. It displays nothing.
echo "my_bash_function" | xargs -I{} bash -vc "$(declare -f {})"
  1. However, if the placeholder is replaced with the function name, it works.
echo "my_bash_function" | xargs -I{} bash -vc "$(declare -f my_bash_function)"
  1. Using single quotes, simply displays the command itself even if the function doesn't exit. Which means it isn't evaluating and/or executing it.
echo "my_bash_function" | xargs -I{} bash -vc "$(declare -f {})"
$(declare -f my_bash_function)
declare -f my_bash_function

Please explain why number (3) does not behave as expected?

2

There are 2 best solutions below

9
Barmar On BEST ANSWER

The reason you need -v in #2 is because you're using command substitution. So it executes declare -f my_bash_function, which outputs the function definition. This is then substituted into the bash -c argument, which makes the subshell execute the code that defines the function. When you add -v it prints the commands that it's executing, so you see the function definition.

The reason that #3 doesn't work is that the command substitution $(declare -f {}) is being performed by the original shell, not the shell started by xargs. So it's looking for a function named {}, which doesn't exist.

It seems like you're trying to use $(declare -f my_bash_function) to export the function to the subshell. You can use export -f my_bash_function to put the function in the environment, and it will be exported automatically.

0
Charles Duffy On

Expansions in double-quoted strings are run by your local shell, before xargs is started. This means that values introduced by xargs cannot be used in those expansions, because xargs hasn't yet been run!


That is to say, when you run:

echo "my_bash_function" | xargs -I{} bash -vc "$(declare -f {})"

your shell first runs

declare -f {}

which (in bash 5.2.15) emits no output at all.

Consequently, it's replaced with:

echo "my_bash_function" | xargs -I{} bash -vc ''

...which, as one might expect, does nothing useful.