4

I have to write a small multithreaded mysqldump script for our database and I got some problems because of a single table containing a space.

My first attempt was quite easy:

for TABLE in `mysql -u user -ppassword -e 'show tables;' dbname`  
do
    while [ 1 ]
    do
        if [ `jobs -r | wc -l` -lt $MAXTHREADS ]
        then
            break
        else
            sleep 1
        fi
    done

    mysqldump -u user -ppassword dbname $TABLE
done

Unfortunetely there was a table which contained a space. I googled a little bit for using the for loop with multiline output from commands and changing the $IFS variable was a common solution. So I changed it to \n\b (somehow $IFS was empty when I only used \n) but that was a bad idea because it caused the mysql commands to not work anymore.

I thought that this shouldn't be a problem when I get the tables beforehand and change the $IFS back everytime I use mysqldump in the for loop. But again I was mistaken as I only have one line of all tables now.
My current code:

TABLES=$(mysql -u user -ppassword -e "show tables" dbname | tail -n +2)

OIFS="$IFS"
AIFS=$(echo -en "\n\b")
IFS="$AIFS"

for TABLE in "$TABLES"
do
    IFS="$OIFS"
    while [ 1 ]
    do
        if [ `jobs -r | wc -l` -lt $MAXTHREADS ]
        then
            break
        else
            sleep 1
        fi
    done

    mysqldump -u user -ppassword dbname $TABLE
    IFS="$AIFS"

done
IFS="$OIFS"

When I try to echo the $TABLES variable I get one table per line, but the for loop is only running once with the $TABLE variable containing ALL the tables.

Thanks in advance
kiro

1
  • To set IFS to a newline in Bash: IFS=$'\n' Commented Jun 8, 2012 at 16:14

1 Answer 1

6

Use a while loop instead of for:

mysql -u user -ppassword -e "show tables" dbname | tail -n +2 | while read TABLE
do
    ...
done

...unless you need to set any variables inside the loop and have them available after the loop exits. Since this makes the while loop part of a pipeline, it runs in a subshell, and variables and such don't transfer to the main shell. If you need the loop to run in the main shell, you can use bash's process substitution feature instead of a standard pipe:

while read TABLE
do
    ...
done < <(mysql -u user -ppassword -e "show tables" dbname | tail -n +2)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.