回答:
Arturoのソリューションの次の変更を使用します。
psql -lqt | cut -d \| -f 1 | grep -qw <db_name>
psql -l
次のようなものを出力します:
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+-----------+----------+------------+------------+-----------------------
my_db | my_user | UTF8 | en_US.UTF8 | en_US.UTF8 |
postgres | postgres | LATIN1 | en_US | en_US |
template0 | postgres | LATIN1 | en_US | en_US | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | LATIN1 | en_US | en_US | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
素朴なアプローチを使用すると、「List」、「Access」、または「rows」というデータベースの検索が成功します。したがって、この出力を組み込みのコマンドラインツールの束にパイプして、最初の列のみを検索します。
-t
フラグは、ヘッダとフッタを削除します。
my_db | my_user | UTF8 | en_US.UTF8 | en_US.UTF8 |
postgres | postgres | LATIN1 | en_US | en_US |
template0 | postgres | LATIN1 | en_US | en_US | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | LATIN1 | en_US | en_US | =c/postgres +
| | | | | postgres=CTc/postgres
次のビットはcut -d \| -f 1
、出力を垂直パイプ|
文字(シェルからバックスラッシュでエスケープしたもの)で分割し、フィールド1を選択します。
my_db
postgres
template0
template1
grep -w
単語全体に一致するためtemp
、このシナリオで検索している場合は一致しません。この-q
オプションは、画面に書き込まれる出力を抑制します。そのため、コマンドプロンプトでこれをインタラクティブに実行する場合は、除外して-q
、何かがすぐに表示されるようにすることができます。
はgrep -w
、英数字、数字、およびアンダースコアに一致することに注意してください。これは、postgresqlの引用符で囲まれていないデータベース名で許可されている文字のセットです(引用符で囲まれていない識別子ではハイフンは無効です)。他の文字を使用している場合は、grep -w
機能しません。
このパイプライン全体の終了ステータスは0
、データベースが存在する場合は(成功)、存在1
しない場合は(失敗)になります。シェルは特殊変数$?
を最後のコマンドの終了ステータスに設定します。条件で直接ステータスをテストすることもできます。
if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
# database exists
# $? is 0
else
# ruh-roh
# $? is 1
fi
wc
完全に削除します。私の改訂版をご覧ください。(あなたは終了ステータスを逆にしたい場合は、bashは強打演算子をサポートしています。! psql ...
)
wc
コマンドを削除する他の提案に加えて、私はを使用しますgrep -qw <term>
。これにより、0
一致するものがあればシェルが戻り1
ます。次に、$?
戻り値が含まれ、それを使用して次に何をするかを決定できます。したがって、wc
この場合は使用しないことをお勧めします。grep
あなたが必要なことをします。
次のシェルコードは私にはうまくいくようです:
if [ "$( psql -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" )" = '1' ]
then
echo "Database already exists"
else
echo "Database does not exist"
fi
psql -U user -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" template1
if [[ $(...) == 1* ]]
postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l
指定したデータベースが存在する場合は1を返し、それ以外の場合は0を返します。
また、すでに存在するデータベースを作成しようとすると、postgresqlは次のようなエラーメッセージを返します。
postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR: database "template1" already exists
exact_dbname_test
でしょうか?テストの唯一の方法は、それに接続することです。
psql -l | grep doesnt_matter_what_you_grep | wc -l && echo "true"
vspsql -l | grep it_does_matter_here && echo "only true if grep returns anything"
psql -l | grep '^ exact_dbname\b'
見つからない場合に終了コードが設定されます。
postgresqlは初めてですが、次のコマンドは、データベースが存在するかどうかを確認するために使用したものです
if psql ${DB_NAME} -c '\q' 2>&1; then
echo "database ${DB_NAME} exists"
fi
psql ${DB_NAME} -c ''
。
私は簡潔でPOSIX互換の形式に他の答えを組み合わせています:
psql -lqtA | grep -q "^$DB_NAME|"
true
(0
)の戻りは、それが存在することを意味します。
データベース名になどの非標準文字が含まれていると思われる$
場合は、少し長いアプローチが必要です。
psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"
-t
および-A
オプションは、出力が生および「表形式」または空白詰め出力されていないことを確認してください。列はパイプ文字|
で区切られているため、cut
またははgrep
これを認識する必要があります。最初の列にはデータベース名が含まれています。
編集:部分的な名前の一致を防ぐために-xを指定したgrep。
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#
完全を期すために、文字列カットではなく正規表現を使用する別のバージョン:
psql -l | grep '^ exact_dbname\b'
たとえば:
if psql -l | grep '^ mydatabase\b' > /dev/null ; then
echo "Database exists already."
exit
fi
\b
すると、を使用したすべての回答と同じ問題grep -w
があります。つまり、データベース名にはのような非単語構成文字を含めることができる-
ため、照合しようとするfoo
とも照合されfoo-bar
ます。
kibibuの受け入れられた回答は、指定されたパターンを単語構成要素として含むすべての名前にgrep -w
一致するという点で欠陥があります。
つまり、「foo」を検索すると、「foo-backup」が一致します。
オセウスの答えはいくつかの優れた改善を提供し、短いバージョンはほとんどの場合正しく動作しますが、提供される2つのバリアントのうち長い方は、部分文字列の一致に関して同様の問題を示します。
この問題を解決するには、POSIX -x
引数を使用して、テキストの行全体のみを照合します。
オセウスの答えに基づいて、新しいバージョンは次のようになります。
psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"
とはいえ、特定のデータベースについて実際にpostgresに質問するNicolas Grillyの回答が、すべての中で最も優れたアプローチであると言える傾向があります。
他のソリューション(これは素晴らしい)は、psqlがホストに接続できない場合、タイムアウトする前に1分以上待機する可能性があるという事実を見逃しています。だから、私はタイムアウトを3秒に設定するこのソリューションが好きです:
PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""
これは、公式のpostgres Alpine Dockerイメージ上の開発データベースに接続するためのものです。
それとは別に、Railsを使用していて、データベースがまだ存在しない場合にデータベースをセットアップする場合(Dockerコンテナーを起動するときなど)、移行はべき等であるため、これはうまく機能します。
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
私はまだシェルプログラミングにまだ慣れていないので、これがなんらかの理由で本当に間違っている場合は、投票してください。
キビブの答えから構築:
# If resulting string is not zero-length (not empty) then...
if [[ ! -z `psql -lqt | cut -d \| -f 1 | grep -w $DB_NAME` ]]; then
echo "Database $DB_NAME exists."
else
echo "No existing databases are named $DB_NAME."
fi
... | grep 0
して、DBが存在しない場合はシェルの戻り値を0、存在する場合は1にすることもできます。または... | grep 1
逆の動作