Reputation: 9148
Consider the following in a simple shell script meant to dump a mysql dbtable:
if [ $account -eq 1 ]; then
echo "Dumping user table ... "
mysqldump --host='dbhost.com' --user=someUser -p'somePW' dbName --no-create-info --single-transaction --tables user --where="id=${USER_ID}" > account_data/user.sql
fi
How would one have the above command properly parsed / quoted?
Running in -x mode shows the following:
mysqldump --host=dbhost.com --user=someUser '-psomePW' dbname --no-create-info --single-transaction --tables user --where=id=283
It still works, but it seems it does not look right having the arguments non-quoted, and the single quotes on password argument enclose the whole argument?!?
Why, Bash, why?!?
Upvotes: 1
Views: 58
Reputation: 80931
Double and single quotes aren't magical. They simply protect the shell from interpreting the contents in ways it otherwise would.
Single quotes prevent the shell from interpreting anything inside them. The only thing that is special inside a single quoted string is a single quote and that ends the string.
Double quotes prevent filename globbing, etc. but allow variable expansions and the like.
Both quotes prevent the shell from word splitting (breaking input up into words on whitespace).
This line
echo foo bar baz
is four words to the shell.
Both of these
echo "foo bar baz"
echo 'foo bar baz'
are two "words".
After quote removal any words that are touching are combined by the shell so this is also two "words"
echo "foo bar"' baz'
Let us look at your examples now
mysqldump --host='dbhost.com' --user=someUser -p'somePW' dbName --no-create-info --single-transaction --tables user --where="id=${USER_ID}" > account_data/user.sql
mysqldump --host=dbhost.com --user=someUser '-psomePW' dbname --no-create-info --single-transaction --tables user --where=id=283
Assume USER_ID
has a value of 283
.
Expand the variables and remove the quotes from both and we get
mysqldump --host=dbhost.com --user=someUser -psomePW dbName --no-create-info --single-transaction --tables user --where=id=${USER_ID} > account_data/user.sql
mysqldump --host=dbhost.com --user=someUser -psomePW dbname --no-create-info --single-transaction --tables user --where=id=283
and you see why the quoting in both works the same way. They end up with the same result.
The quoting is all before the command execution. The command doesn't see the quotes any more than it sees the variables themselves.
If you run set -x
in your shell the shell will show you the commands that are going to be run as it runs them (in an format that shows the "words" it sees).
How you choose to quote arguments like --host='dbhost.com'
is up to personal style and what the value is. Those quotes aren't necessary. They could just as validly go around the entire string ('--host=dbhost.com'
) or arbitrarily around any part of the argument (--hos't='dbhost.com
).
If you want to read more about how all this works in detail you can read the Shell Command Language section of the POSIX spec.
Upvotes: 3