Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

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;
share|improve this question

7 Answers 7

up vote 3 down vote accepted

Use 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

share|improve this answer
2  
This isn't the problem at all -- wildcards don't get expanded inside double-quotes either, so (other than removing the backslash) this is the same as what the question had. The real problem is how c is used, not how it's defined. See Gilles, slillibri, and Dennis Williamson's answers for more relevant solutions. –  Gordon Davisson Jul 25 '10 at 1:14

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"
share|improve this answer
  1. 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.

  2. 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
    
  3. 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.

share|improve this answer

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 ~]$ 
share|improve this answer

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"
share|improve this answer

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;
share|improve this answer
    
Will this not treat $c as a file name –  Rohit Banga Oct 1 '13 at 23:51

This will work in bash, no escaping necessary

#!/bin/bash
mysql -u root -e "GRANT ALL ON *.* TO '$1'@'localhost'"
exit 0;
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.