Search code examples
bashsubshell

strange behaviour of a subshell executing command with arguments


when I execute the following command directly:

root@busybox-694d76bb5d-2gcvh:/# mysql -hmariadb -P3306 -uroot -ppassword -e 'SELECT 1'

I get the following output:

mysql: [Warning] Using a password on the command line interface can be insecure.
+---+
| 1 |
+---+
| 1 |
+---+

However, the same command in a subshell, like so:

$(mysql -hmariadb -P3306 -uroot -ppassword -e 'SELECT 1')

outputs:

mysql: [Warning] Using a password on the command line interface can be insecure.
bash: 1: command not found

why does bash interprets the "1" I send as an argument as if it was a separate command when it is sent in a subshell?


Solution

  • It's not the 1 that's part of the arguments that is interpreted by bash, it's the output of the command.

    First, you need to know that mysql has two default modes of output : table and raw. The first is used when the command's output stream is a terminal and prints an human-readable output. The second is used otherwise and prints an output easily manipulated by scripts. You can force one or the other by using the options whose documentation I've linked.

    Secondly, you need to know the difference between a simple (subshell) and $(command substitution) : in both cases the command is run in a subshell, but with command substitution the output of the command is substituted in the original command line which is then executed.

    So what happened when you wrote your $(mysql command) is that its output was 1 (the raw result) instead of the table you previously saw, which then failed to be parsed as a command.

    You can see the difference between subshell and command substitution more easily by testing the difference between (echo 1) and $(echo 1), the second of which will fail in the exact same way as your current command.