Reputation: 4816
Unfortunatly psql -l
uses linewraps
example see output and regard the "access" column
List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -------------------------+------------+----------+-------------+-------------+----------------------- firstdb | postgres | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | secnddb | scnduser | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | thrddb | scnduser | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | postgres | postgres | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | template0 | postgres | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres (6 rows)
hint even with some option, I can't get that gone:
$ psql -Atlqn firstdb|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8| secnddb|scnduser|UTF8|de_DE.UTF-8|de_DE.UTF-8| thrddb|scnduser|UTF8|de_DE.UTF-8|de_DE.UTF-8| postgres|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8| template0|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|=c/postgres postgres=CTc/postgres template1|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|=c/postgres postgres=CTc/postgres
Question Is there another way to get the list of databases in the same way \list
prints it so I can use it in scripts for parsing with e.g. awk?
Upvotes: 1
Views: 1040
Reputation: 324265
Interesting issue. You're being bitten by hard linewraps in ACL entries. Those aren't the only place they can appear btw, just the most common.
Rather than trying to avoid the newlines, why not use a different record separator? A null byte (\0
) can be good; that's what the -0
option is for. It's only useful if your client can deal with null bytes, though; good for xargs -0
, not good for lots of other stuff. The handy thing about a null byte is that it won't appear in psql
's output otherwise so there's no risk of conflict. gawk
does support null-separated records, though it's woefully underdocumented.
Try, e.g:
psql -Atlqn -0 | gawk -vRS=$'\0' '{ gsub("\n", " "); print }
which replaces newlines in database names (yes, they can appear there!), ACL entries, etc with a space.
Alternately, use -R
, e.g. -R '!'
or -R '--SEPARATOR--'
or whatever is easy for you to parse and not likely to appear in the output.
Depending on the information you need, you can instead query the catalogs or information_schema
directly, too. You'll still have to deal with funny chars, so you may want a regexp to escape any funny business.
Beware that you still have to deal with unexpected newlines; consider what happens when some @#$@ does this:
CREATE DATABASE "my
database";
Yes, that's a legal database name. So are both of:
CREATE DATABASE "$(rm -rf /gladthisisnotroot);";
CREATE DATABASE "$(createuser -l -s my_haxxor -W top_secret)"
Yes, both are legal database names. Yes, that's really, really bad if you don't escape your shell metacharacters properly, you made the mistake of running your shell scripts as root or the postgres
user, and they're not feeling nice.
Upvotes: 2
Reputation: 4816
All relevant data is in pg_database
and pg_user
see http://www.postgresql.org/docs/current/static/catalog-pg-database.html
select pg_database.datname,pg_user.usename,pg_encoding_to_char(pg_database.encoding),pg_database.datcollate,pg_database.datctype,pg_database.datacl from pg_database,pg_user WHERE pg_database.datdba = pg_user.usesysid;
on shell, wrapped in psql command:
psql -AStnq -c "select [...]"
returns correct formatted
template1|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|{=c/postgres,postgres=CTc/postgres} template0|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|{=c/postgres,postgres=CTc/postgres} postgres|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8| firstdb|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8| secnddb|scnduser|UTF8|de_DE.UTF-8|de_DE.UTF-8| thrddb|scnduser|UTF8|de_DE.UTF-8|de_DE.UTF-8|
Upvotes: 2