Question: I have this bash script:

```
databases=`mysql -h$DBHOST -u$DBUSER -p$DBPASSWORD -e "SHOW DATABASES;" | tr -d "| " | grep -v Database`

```

and the issue is when the password has all the characters possible. how can i escape the `$DBPASSWORD` in this case? If I have a password with '!' and given the fact that command is inside backticks. I have no experience in bash scripts but I've tried with `"$DBPASSWORD"` and with `'$DBPASSWORD'` and it doesn't work. Thank you

LATER EDIT: link to script here, line 170 -> <https://github.com/Ardakilic/backmeup/blob/master/backmeup.sh>

Answer: 
Don't pass the MySQL password on the command line. One, it can be tricky with passwords containing shell meta-characters (as you've discovered). Two, importantly, someone using `ps` can sniff the password.

Instead, either put the password into the system `my.cnf`, your user configuration file (eg `.mylogin.cnf`) or create an on-demand file to hold the password:

```
function mysql() {
    local tmpfile=$(mktemp)
    cat > "$tmpfile" <<EOCNF
[client]
password=$DBPASSWORD
EOCNF
    mysql --defaults-extra-file="$tmpfile" -u"$DBUSER" -h"$DBHOST" "$@"
    rm "$tmpfile"
}

```

Then you can run it as:

```
mysql -e "SHOW DATABASES" | tr -d "| " ....
mysql -e "SELECT * FROM table" | grep -v ...

```

See the [MySQL docs on configuration files](https://dev.mysql.com/doc/refman/5.7/en/option-files.html) for further examples.
I sometimes have the same problem when automating activities:

* I have a variable containing a string (usually a password) that is set in a config file or passed on the command-line, and that string includes the '`!`' character.
* I need to pass that variable's value to another program, as a command-line argument.
* If I pass the variable unquoted, or in double-quotes (`"$password"`), the shell tries to interpret the '`!`', which fails.
* If I pass the variable in single quotes (`'$password'`), the variable isn't expanded.

One solution is to construct the full command in a variable and then use `eval`, for example:

```
#!/bin/bash
username=myuser
password='my_pass!'
cmd="/usr/bin/someprog -user '$username' -pass '$password'"
eval "$cmd"

```

Another solution is to write the command to a temporary file and then `source` the file:

```
#!/bin/bash
username=myuser
password='my_pass!'
cmd_tmp=$HOME/.tmp.$$
touch $cmd_tmp
chmod 600 $cmd_tmp
cat > $cmd_tmp <<END
/usr/bin/someprog -user '$username' -pass '$password'
END
source $cmd_tmp
rm -f $cmd_tmp

```

Using `eval` is simple, but writing a file allows for multiple complex commands.

P.S. Yes, I know that passing passwords on the command-line isn't secure - there is no need for more virtue-signalling comments on that topic.