The problem lies in the fact that you have nested quotes, which makes quoting somewhat involved. Since you don't have a "comprehensive" quote around your arguments to echo
, all your attempts (except for your 3rd attempt(1)) are actually passing three arguments to echo
, which are all subject to quote removal:
The key point is that upon interpretation of the "outer" command, the outer quotes of the argument to bash -c
are removed. The inner quotes remain, either because they are escaped or because they are of different type than the outer ones.
Then, when the bash
instance you explicitly called processes that argument (the "inner" command), it itself performs quote-removal when interpreting the arguments to the echo
call. Thus, the quotes you put around Hello, World!
will ensure that this is considered one argument to echo
, but be removed in the same process (and thereby lost to echo
).
Since you don't need variable expansion in the ("inner") echo
command, I would go with the single-quote syntax as follows:
bash -c 'echo "I say \"Hello, World\"!"'
That way you are passing one single argument to echo
, and the quote-escaping inside the double-quotes will work as expected.
(1) In the 3rd attempt you show, you are actually passing 2 arguments to bash -c
:
echo I say Hello,
and
World!
leading to four arguments to echo
seen by the "inner" command. This is because your attempt to "interrupt" the outer double-quotes with """
doesn't work that way - instead, the first of these double-quotes mean that the starting double-quote of the bash -c
argument is closed after the space. This is then seen as being followed by an empty double-quoted string, and then by an unquoted Hello,
. All these are concatenated because there is no space in between them.
Then, since the space following is unprotected, the outer bash
will now consider the remainder a second argument, starting with the (again unquoted) World
, a double-quoted empty string, and then an opened-but-unclosed double-quoted string containing '!'
. The fact that it is not correctly closed is masked by the error message you should receive about an "event not found", since the starting double-quote makes the following single-quote merely a character to-be-printed, whereby the !
is no longer protected from interpretation as history reference.