3

In my mysql restore script I use a mysqldump file previously created for input. This filename is provided on the command line as an argument and may or may not be gzipped. I want to use the file as input to the mysql statement but not change/gunzip the file, just read the contents.

I use the following code for input to the mysql command (which I like):

mysql -u $user -p"$pass" $dbname <( [[ "${mysqldumpfile: -3}" = ".gz" ]] && gzip -d -c "${mysqldumpfile}" || cat "${mysqldumpfile}" )

So mysql dump file name ends in ".gz" then I gunzip to stdout, otherwise I cat to stdout. stdout from either is used as stdin to the mysql command.

Is this a UUOC? Is there a way to NOT use cat?

Is there another way to do this (on one line)? And to be clear I don't want to check in an if/then/else/ statement and do two different mysql commands. I like one command line that can use two different inputs.

EDIT: Since zcat -f will both uncompress and cat or just cat if the data isn't compressed, this isn't the best example. I'd still like to know if there is another way to <( test && do_this_command_as_input || cat this_is_the_input ) and not use cat.

And before someone mentions it ... you can't input to a mysql command line using <( ).

2

This is not the cat you're looking for :)

mysql -u $user -p"$pass" $dbname <(zcat -f  $mysqldumpfile)

Edit: forgot parentheses

Edit 2:

Ok totally without cat or zcat this time:

gunzip -f $mysqldumpfile 2>/dev/null; mysql -u $user -p"$pass" $dbname < ${mysqldumpfile%%.gz}

Prefer the first option though

Ok 3rd version and I'm done :P

mysql -u $user -p"$pass" $dbname < (gzip -fdc $mysqldumpfile)
| improve this answer | |
  • So a bad example, in this case zcat -f will act like cat... guess I'll have to fix the question. – johnnyB Sep 25 '13 at 19:01
  • added a cat/zcat-less version – Nanzikambe Sep 25 '13 at 19:21
3

This is not useless use of cat.

You need the cat because it is the neutral filter in place of gzip. Either process the file through gzip and then dump to stdout, or do no processing and dump to stdout.

Suppose you get only gzipped files then the command would look like this:

mysql -u $user -p"$pass" $dbname <( gzip -d -c "${mysqldumpfile}" )

Now the requirements change and you get only plain files:

mysql -u $user -p"$pass" $dbname <( cat "${mysqldumpfile}" )

That would be a useless use of cat because that can be simplifed to this:

mysql -u $user -p"$pass" $dbname "${mysqldumpfile}"

In your command you cannot skip the cat because you cannot skip the process substitution.


Here is your command with a verbose if then else but only one mysql line.

togzip_ornottogzip() {
  if [[ "${mysqldumpfile: -3}" = ".gz" ]]; then
    gzip -d -c "${mysqldumpfile}"
  else
    cat "${mysqldumpfile}"
  fi
}

mysql -u $user -p"$pass" $dbname <( togzip_ornottogzip )

Now my suggestion on how to write the command even better:

I suggest you rewrite your script to always expect plain files as input in stdin:

mysql -u $user -p"$pass" $dbname <( cat )

Lets call this script domysql_stdin

Then write two scripts, both taking a filename as argument. One expects gzipped files and the other expects plain files. Both will then redirect the output to the first script.

The one expecting gzipped files:

gzip -d -c "${mysqldumpfile}" | domysql_stdin

The one expecting plain files:

domysql_stdin < "${mysqldumpfile}"

Lets call them domysql_gzipped and domysql_plain

Then write a fourth script which takes a filename as argument, check whether the file is gzipped or not and then call the gzipped expecting script or the plain expecting script.

if [[ "${mysqldumpfile: -3}" = ".gz" ]]; then
  how="gzipped"
else
  how="plain"
fi

domysql_$how "${mysqldumpfile}"

This way each script does a simple thing and each part is usable on it's own.

Instead of four files you can also put everything in one file with four functions. You just have to be carefull with name collisions and variable visibility and lifetime.

| improve this answer | |
  • Too verbose, and leaves input decompressed (presume that's nuked later, but still) – Nanzikambe Sep 25 '13 at 18:47
  • Well I'm glad you commented before I did my edit. My improved suggestion is even more verbose. What do you mean with "leaves input decompressed"? The gzip command as it stand decompresses to stdout. There is no file written. – lesmana Sep 25 '13 at 19:24
  • my bad, I presumed gzip was a typo for gunzip which would leave the file on disk. Though you've given me an idea ... – Nanzikambe Sep 25 '13 at 19:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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