0

Imagine I want to call some command some-command via $() with an argument stored in another variable argument, the latter containing space.

  1. With my current understanding, the fact that result="$(some-command $argument)" (e.g. expansion) leads to passing two arguments is as expected.

  2. Question part: why does the result="$(some-command "$argument")" (e.g. concatenation) lead to the desired result of passing one single argument?

More details:

./some-command:

#!/usr/bin/env bash
echo "Arg 1: $1"
echo "Arg 2: $2"

./test-script:

#!/usr/bin/env bash

export PATH="`pwd -P`:$PATH"

argument="one two"

echo "Calling with expansion"
res="$(some-command $argument)"
echo $res

echo "Calling with concatenation"
res="$(some-command "$argument")"
echo $res

Calling test-script leads to the following output:

Calling with expansion
Arg 1: one Arg 2: two
Calling with concatenation
Arg 1: one two Arg 2:

I seem to not grasp when smth is expanded / evaluated and how the expanded variables are grouped into arguments passed to scripts.

Thank you!

P.S. Bonus curiosity is why result="$(some-command \"$argument\")" does not work at all.

4
  • 1
    Do you have a space after some-command or not? Commented Mar 2, 2021 at 17:05
  • Good catch, inactual scripts space is there, corrected! Commented Mar 2, 2021 at 17:07
  • BashFAQ #50 is your friend -- it explains why argument lists should never be stored as strings, and what to use instead (short form: either arrays or functions, depending on the context). Commented Mar 2, 2021 at 17:19
  • ...as for result="$(some-command \"$argument\")", if argument="one two", it's running some-command '"one' 'two"' Commented Mar 2, 2021 at 17:27

1 Answer 1

1

That's how quoting and expansions work in bash. In fact, double quotes after = are not needed, as word-splitting is not performed, so

result=$(some-command "$argument")

should work the same way.

There's no "concatenation" going on. Bash treats the string inside $() as a command and runs all the expansions on it before running it.

So, what happens with some-command "$argument"? First, the parameter expansion expands $argument into a string containing spaces. When word-splitting happens, it notes the string was enclosed in double quotes, so it keeps it as a single string.

Sign up to request clarification or add additional context in comments.

3 Comments

I see, thanks! So in this case the relation between the outer pair of quotes and the inner one is not the same as in say res="literal1"$stringvar2"literal3"? I.e. the quoted part is not “switched off/on” but bash rather recognizes those as quotes inside quotes?
@agronskiy: Exactly.
Thank you! Should have had closer look to the dup question...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.