対話モードでメタコマンド「\oファイル名」を実行すれば、再び「\o」を打つまで自動的にファイルへ追記書き込みされます。ただし表示形式がコンソールと同じなので、タブ区切り(TSV)やカンマ区切り(CSV)にするには一手間必要。Windows 7 64bit + PostgreSQL 9.5.0で動作確認しました。
Contents


関連サイト

公式ドキュメントは下記。ちょうど真ん中あたりにメタコマンド\oの説明があります。

下記ML、ブログではパイプでcatコマンドに渡して追記書き込みする例が載っていますが、自分の環境では単純にファイルを指定するだけで可能でした。

対話モードでなくコマンドラインから実行する例は下記を参照。と言っても、単に出力先を「>>ファイル名」とリダイレクトするだけですが。

基本形

冒頭に書いたとおり「\oファイル名」を実行すれば、再び「\o」だけを打つまで、すべての出力結果がファイルに追記されます。ファイルパスはWindowsでもスラッシュ区切りだけで良く、逆にクォートするとNGでした。↓ の例では最初に表示形式をMySQL風にしており、ファイルにもその通り出力されます。\oを打つまではpsqlがファイルを開いているので、他のエディタで見たりする時は注意が必要。
\pset border 2
\o R:/test_psql.txt

-- NG: \o "R:/test_psql.txt"
-- NG: \o '"R:/test_psql.txt"'

select 1;
select 2;
select 3;

-- close the file
\o

-- content of the file
+----------+
| ?column? |
+----------+
|        1 |
+----------+
(1 row)

+----------+
| ?column? |
+----------+
|        2 |
+----------+
(1 row)

+----------+
| ?column? |
+----------+
|        3 |
+----------+
(1 row)


タブ区切り(TSV)で追記書き込み

前項のとおり\oコマンドは「コンソールの代わりにファイルへ書き込む」ので、タブ区切りにしたければ表示設定の変更が必要。↓ は「横方向の揃えなし」「データのみ」「列間をタブ区切り」と三つ設定した後、\oで続けて2回出力しました。追記書き込みだから1回目・2回目のクエリ結果が切れ目なくつながってます。
\pset format unaligned
\pset tuples_only on
\pset fieldsep '\t'

\o R:/test_psql.tsv

select *, random() from generate_series(1, 10);
select *, random() from generate_series(11, 20);

-- close the file
\o


カンマ区切り(CSV)で追記書き込み

TSVとの違いは列間の区切りをカンマにする(\pset fieldsep ',')だけ。ただし各フィールドを引用符で括ることはpsqlの表示設定ではできず、空の列は ↓ のようにカンマが連続してしまいます。COPYコマンドを使えば引用符つき出力できるので、いずれ別記事に。
\pset format unaligned
\pset tuples_only on

-- to output csv
\pset fieldsep ','

\o R:/test_psql.csv

select *, text '', random() from generate_series(1, 10);
select *, text '', random() from generate_series(11, 20);

-- close the file
\o


一回ごとに区切り線や印を付けながら、追記書き込み

例えば長いデータをずらずらと一ファイルに出力したいけど、一定行数ごとに区切り線や印を入れたい場合とか。メタコマンドの\qechoで、任意の文字列をはさめます。\echoだとファイルでなくコンソールに表示されるので注意。
\pset format unaligned
\pset tuples_only on
\pset fieldsep '\t'

\o R:/test_psql_sep.tsv

select *, random() from generate_series(1, 10);
\qecho -----
select *, random() from generate_series(11, 20);

-- close the file
\o


クエリだけでなく、メタコマンドの出力結果もファイルに追記できる

今回の\oを使えば、データベース一覧の\l、テーブル一覧の\dなどメタコマンドの出力結果もファイルに追記書き込みできます。コンソールの幅が狭くともファイルには折り返し無しで出力されるので便利。
\pset format aligned
Output format is aligned.

\pset border 2
Border style is 2.

\pset tuples_only off
Tuples only is off.

\o R:/test_metacommand.txt
\l
\o

-- content of the file
                                List of databases
+----------------+----------+----------+---------+-------+-----------------------+
|      Name      |  Owner   | Encoding | Collate | Ctype |   Access privileges   |
+----------------+----------+----------+---------+-------+-----------------------+
| postgres       | postgres | UTF8     | C       | C     |                       |
| template0      | postgres | UTF8     | C       | C     | =c/postgres          +|
|                |          |          |         |       | postgres=CTc/postgres |
| template1      | postgres | UTF8     | C       | C     | =c/postgres          +|
|                |          |          |         |       | postgres=CTc/postgres |
| test_postgis22 | postgres | UTF8     | C       | C     |                       |
+----------------+----------+----------+---------+-------+-----------------------+
(4 rows)


出力ごとにファイルを閉じたいなら、少し面倒だけど\gコマンド

最初の基本形で書いたように、「\oファイル」を実行すると再び\oを打つまでpsqlがファイルを開き放しになり、ファイル移動や他のエディタでの編集ができません。ちょっと不便なので1回の出力ごとにファイルを閉じる方法を調べた結果が ↓ こんな感じ。先にクエリをセミコロン抜きで書き(寸止め)、\gコマンド(問い合わせバッファの実行)の出力先をリダイレクトして追記してます。
\pset border 2
Border style is 2.

select generate_series(1, 10) -- セミコロン抜きで寸止め
\g | find /v "" > R:/write_and_close.txt

-- 上はファイルに新規書き込み。
-- 実行後はファイルが閉じられるので、他のエディタ等で編集可

select generate_series(11, 20) -- 今度は追記用のクエリを寸止め
\g | find /v "" >> R:/write_and_close.txt

-- これでファイルに追記規書き込み。

\oと違って「\gファイル名」だと常に新規書み込みされるけど、パイプでシェルの標準入力に渡し、そのままリダイレクトすれば新規・追記書き込みともに可能。findコマンドに渡してるのはWindows(CMDシェル)特有の事情で、
「標準入力をそのままリダイレクトする」普通の方法がないから。echoコマンドに渡すと「ECHOONです」とか馬鹿にされるし… でも下記でfindを使う方法を知り、救われました。非Winならもっと簡単だと思います。


このfindを使う方法は、
先月PostGISラスタのコールバック関数を複数テストした時も役立ちました。m(_)m