I just cant do it. If * is in a variable, it expands to a list of files in current folder. echo "*" works fine.
#!/bin/bash
c="GRANT ALL ON \*.* TO '$1'@'localhost';"
mysql < $c
exit 0;
Server Fault is a question and answer site for system and network administrators. It only takes a minute to sign up.
Sign up to join this communityUse single quotes for your string:
c='GRANT ALL ON *.* TO';
c="${c} '$1'@'localhost';";
There is probably a better way to do that but including $1 in the string made it weird
c
is used, not how it's defined. See Gilles, slillibri, and Dennis Williamson's answers for more relevant solutions.
Jul 25, 2010 at 1:14
Always put double quotes around variable substitutions, otherwise characters like spaces and *
appearing in the value are interpreted by the shell. I.e., write "$c"
, not $c
.
The syntax mysql <"$c"
makes mysql
execute commands from a file whose name is the value of $c
. What you're looking for is
printf '%s\n' "$c" | mysql
or simpler, as long as you remember the restrictions ($c
must not start with a -
, and if it contains \
that's ok in bash but not in some other variants of sh)
echo "$c" | mysql
There's another alternative that's more comfortable if the command is multiline. It's called a “here-document”. The string EOF
isn't special (though it's traditional), any sequence of letters and digits will do. The terminating EOF
may not be preceded by whitespace. You need to put a \
before every $
, \
and `
unless you want them interpreted by the shell.
mysql <<EOF
GRANT ALL ON *.* TO '$1'@'localhost';
EOF
Beware that if the argument to the shell contains a single quote, you have an injection vector. The following snippet adds a \
before every \
and '
.
set -- "${1//\\/\\\\}"
set -- "${1//\'/\'}"
This is fairly ugly, which is why if you're going to do anything complicated, forget about using a shell and use a language with actual SQL bindings (perl, python, whatever) where the library handles all the quoting and procedure building for you.
This will work in bash, no escaping necessary
#!/bin/bash
mysql -u root -e "GRANT ALL ON *.* TO '$1'@'localhost'"
exit 0;
First you need to print the SQL command using echo.
Then you need to put quotes around $c
like so:
mysql <( echo "$c" )
Otherwise the value of $c
will be treated as a bash command and thus, the *
will be expanded.
Or a simpler version could be:
mysql -e "$c"
It's no more complicated than this:
#!/bin/bash
c="GRANT ALL ON *.* TO $1@localhost;"
mysql -e "$c"
Or, if you need the single quotes:
#!/bin/bash
c="GRANT ALL ON *.* TO '$1'@'localhost';"
mysql -e "$c"
Simple is perfect! (quote the first part with single quote)
#!/bin/bash
c='GRANT ALL ON *.*' "TO '$1'@'localhost';"
mysql < $c
exit 0;
it should be perfect too! ($c quoted)
#!/bin/bash
c="GRANT ALL ON *.* TO '$1'@'localhost';"
mysql < "$c"
exit 0;
The feature fighting you is shell globbing as part of pathname expansion. Disable this to solve the primary problem you reported. Then use Weboide's suggestion of -e to execute a single command contained in the $c variable through Mysql. Cheers,
[maxwell@elite ~]$ cat me.sh
#!/bin/bash
# disable shell globbing so c variable can be literal
set -f
c="GRANT ALL ON *.* TO '$1'@'localhost';"
echo $c
# enable shell globbing for normal operation
set +f
echo $c
[maxwell@elite ~]$ ./me.sh maxwell
GRANT ALL ON *.* TO 'maxwell'@'localhost';
GRANT ALL ON labserver.etc.0710.tar me.sh Validation.txt TO 'maxwell'@'localhost';
[maxwell@elite ~]$