Search code examples
mysqlmacosshellzsh

Zsh is saying I have an unmatched ' in my shell script. Where is it?


I'm getting an error on line 7 that I have an unmatched ' in my zsh shell script, but I don't see it. What am I missing?

#!/bin/zsh

for f in csvs/*.csv
do
    mytable=$(basename "$f" .csv)
    mysql -e "load data local infile '"$f"' into table '"$mytable"' fields TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' ignore 1 rows"  -u root --password=password --local-infile
done

Solution

  • When you put quotes inside quotes in shell, they become literal characters. So any use of the quotes terminates the quoted string.

    mysql -e "load data local infile '"$f"' into table '"$mytable"' fields ...
             ^start                end^  ^start      end^        ^start...
    

    The single-quotes inside are just characters. They don't escape the double-quote that follows. It's as if you did this:

    mysql -e "load data local infile _"$f"_ into table _"$mytable"_ fields ...
    

    In fact, you don't need to terminate the double-quotes to get shell variables into that string.

    $ foo=string
    $ echo "foo is '$foo'"
    foo is 'string'
    

    Now the source of your error is because you had a case where you need a literal " character in your SQL statement:

    ...ENCLOSED BY '"'...
                 end^
    

    Again, the single-quotes don't do anything to escape this. So the shell thinks it's a termination of your whole double-quoted string. Then it is followed by a ' character that is now outside the double-quoted string, so this one does have special meaning to the shell. That is the unmatched ' in your error.

    You should also escape the backslash in '\n' so MySQL sees the \n.

    In the comments below, we also remembered that the table name must not be in single-quotes.

    So the fix is:

    mysql -e "load data local infile '$f' into table $mytable fields TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' ignore 1 rows"  -u root--password=password --local-infile