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
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
echo I say Hello, and
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.