When dealing with passwords containing exclamation marks in Bash, you're actually encountering Bash's history expansion feature. The !
character triggers this behavior, which attempts to substitute commands from your history rather than treating it as a literal character.
# This fails because Bash tries to find command 'two' in history
$ mysql -umyuser -pone_@&!two
The standard escaping approach using backslashes often fails in this context because:
- Bash performs history expansion before parsing quotes and escapes
- The shell interprets the backslash differently in interactive vs non-interactive modes
# This still fails because history expansion occurs first
$ mysql -umyuser -pone_@&\\!two
Option 1: Single Quotes for the Entire Password
The most reliable method is wrapping the entire password in single quotes:
$ mysql -umyuser -p'one_@&!two'
Option 2: Disable History Expansion Temporarily
For scripts or aliases where quotes aren't feasible:
# In .bashrc or .bash_aliases
alias mysqllogin='set +H; mysql -umyuser -pone_@&!two; set -H'
Option 3: Use Double Quotes with Careful Escaping
When variables are involved:
PASSWORD="one_@&\!two"
mysql -umyuser -p"$PASSWORD"
The most robust solution for your .bashrc would be:
alias mysqlprod='mysql -umyuser --password="one_@&!two"'
For better security, consider using MySQL option files:
[client]
user = myuser
password = one_@&!two
Then connect simply with:
$ mysql --defaults-file=/path/to/my.cnf
When dealing with exclamation marks in passwords within Bash commands, you're encountering Bash's history expansion feature. The shell interprets !
as a special character that references previous commands unless properly escaped.
$ mysql -umyuser -pone_@&!two
-bash: !two: event not found
The standard backslash escape fails because Bash performs history expansion before processing escapes. This explains why your attempt with \!
still resulted in an error:
$ mysql -umyuser -pone_@&\\!two
[1] 22242
-bash: !two: command not found
1. Single Quotes for the Entire Password
The most reliable method is wrapping the entire password in single quotes:
$ mysql -umyuser -p'one_@&!two'
2. Disabling History Expansion Temporarily
For scripts or aliases where quoting isn't practical:
$ set +H
$ mysql -umyuser -pone_@&!two
$ set -H # Re-enable if needed
3. Double Escaping in .bashrc Aliases
For your specific .bashrc case:
alias mysqltest='mysql -umyuser -p"one_@&"'\\''!two'"'"
Using mysql_config_editor
A more secure approach than storing passwords in aliases:
$ mysql_config_editor set --login-path=mypath \
--host=localhost --user=myuser --password
# Then enter the password (including !) at prompt
$ mysql --login-path=mypath
Environment Variables
Store the password in an environment variable:
export MYSQL_PWD='one_@&!two'
mysql -umyuser
While solving the escaping issue is important, consider that:
- Password visibility in process listings can be a security risk
- .bashrc entries may be visible to other users
- MySQL's
--defaults-file
option provides better security
To verify your escaping works correctly without connecting to MySQL:
$ echo 'password_with_!mark' # Test echo first
$ echo 'one_@&!two' # Should output exactly as shown