0

I am trying to write a bash script that creates and sets up a postgres database if it does not already exist. Following this, I've got to this script:

if [ `psql -l | grep mydb | wc -l` -eq 1]
then
    echo "Database exists"
else:
    echo "Creating database"
    ...
fi

But it always returns with "Database exists", regardless of whether the database is there or not. I've also tried [ "` psql -l | grep mydb | wc`" == "1" ], but it gives the same result. What am I doing wrong?

EDIT The output of psql -l and psql -l | grep mydb are:

$ psql -l
                                       List of databases
    Name    |    Owner     | Encoding |   Collate   |    Ctype    |   Access privileges   
------------+--------------+----------+-------------+-------------+-----------------------
 geoserver  | adminhgv7rj4 | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 postgres   | postgres     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 project_db | gis_group    | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0  | postgres     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
            |              |          |             |             | postgres=CTc/postgres
 template1  | postgres     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
            |              |          |             |             | postgres=CTc/postgres
(6 rows)
$ psql -l | grep mydb
$
Community
  • 1
  • 1
aquavitae
  • 17,414
  • 11
  • 63
  • 106
  • What is the output of `psql -l`? And `psql -l | grep mydb`? – fedorqui Dec 12 '13 at 10:34
  • If you just want to test whether that `grep` found something or not, you should use `if psql -l | grep -q mydb; then …`. – Alfe Dec 12 '13 at 10:35
  • @fedorqui I've run those manually to make sure that they are giving the correct output. The output from `psql -l | grep mydb | wc -l` is `0`. If I manually create the database it is `1`, and if I drop it it goes back to `0`. – aquavitae Dec 12 '13 at 10:40
  • @Alfe That doesn't work either. It prints the `grep` result then `Database exists`. – aquavitae Dec 12 '13 at 10:41
  • 1
    You have a strange `grep` if it prints anything when given the option `-q` (for quiet). Have you really given that option? – Alfe Dec 12 '13 at 10:42
  • 1
    But what's the output of `psql -l | grep mydb` alone? And just `psql -l`? – fedorqui Dec 12 '13 at 10:43
  • @Alfe Where do you see `-q`? I haven't used it. – aquavitae Dec 12 '13 at 10:49
  • @aquavitae then you should read my comment more carefully. That `-q` is an option given to `grep`. I propose to use copy & paste to prevent such simple errors. – Alfe Dec 12 '13 at 10:51
  • In the question you are linking there is an alternative: `psql -lqt | cut -d \| -f 1 | grep -w | wc -l`. Give a try to it, as it is safer because it just checks the first column. – fedorqui Dec 12 '13 at 10:52
  • @Alfe Sorry, you're right - I missed it! And it works, thanks! I'll accept it if you post it as an answer. – aquavitae Dec 12 '13 at 10:57

2 Answers2

3

If you just want to test whether that grep found something or not, you should use

if psql -l | grep -q mydb
then
  …
Alfe
  • 56,346
  • 20
  • 107
  • 159
2

The question referred by you includes alternatives that don't require multiple pipes, and seem simpler.

You could say:

( createdb mydb || { echo "creating.." ; false; } ) && echo "database exists"

This is essentially equivalent to saying:

if ! createdb mydb; then
  echo "Creating database";
else
  echo "Database exists"
fi
devnull
  • 118,548
  • 33
  • 236
  • 227
  • Thanks for the suggestion, but I've got a whole list of commands I need to run if the database doesn't exist, and I can't wrap them all like that. – aquavitae Dec 12 '13 at 10:52
  • @aquavitae I'm not sure what you mean by `I can't wrap them all like that` -- you could insert multiple statements in any of the blocks. – devnull Dec 12 '13 at 11:04
  • Oh, you mean use the second form, and include the extra code in below the `echo`s. Yes, that could work! – aquavitae Dec 12 '13 at 11:14
  • @aquavitae: .. or you could invoke a function (instead of echo "..." ; other statements ) that has multiple statements and outputs a proper return code when it finishes. Could improve readability ? ie : `( createdb mydb || { func1 ; } ) && func2` (as devnull proposed. Note however that func2 occurs if **either** createdb or func1 worked! and 'echo' always works! ) – Olivier Dulac Dec 12 '13 at 12:08
  • @devnull: in the current form `( createdb mydb || { echo "creating.." ; } ) && echo "database exists"` I believe it will always output `database exists` (sometimes preceded by `creating...`) as the `&& echo "database exists"` occurs if either `createdb mydb` OR `echo "creating..."` outputs a 0, and echo will output 0.Therefore it is **not** equivalent to the if/then/else/fi you put underneath – Olivier Dulac Dec 12 '13 at 12:14
  • @OlivierDulac Yes, the shorter form should have been: `( createdb mydb || { echo "creating.." ; false; } ) && echo "database exists"` to be __equivalent__ to the if/then/else/fi variant. – devnull Dec 12 '13 at 12:18
  • @devnull: it's better indeed. But I'd `{echo "createdb failed" ; false;}` or `{echo "you need to create mydb" ;false; }` instead of `{echo "creating..."` ; false; }` ? – Olivier Dulac Dec 12 '13 at 12:20
  • @OlivierDulac error messages can be customized as per user needs. FWIW, one might even localize those. Appreciate your inputs, nevertheless. – devnull Dec 12 '13 at 12:27