たまにしかやらないだろうし、必ず忘れてしまうのでメモしておくものです。

スクリプトに以下のようなヒアドキュメントがあるとする。ファイル名はspit.shとする。

# /bin/bash

cat <<EOS
1 foo
2 bar
3 baz
EOS

スクリプトの引数にファイル名を与えたときにはファイルに書き出し、何も与えなかったときには標準出力に書き出したい。二者択一です。普通のリダイレクトで何とかならないかなと思ったら意外と難しい。

検索した結果、Redirect output to either stdout or a file (not both) - StackExchangeを発見。

結論は条件分岐してexec 1>>$filenameでリダイレクトするということです。この1はファイルディスクリプタの1

/dev/stdoutを使って条件分岐する方法もありかなと思いますが強引な気がするのでこちらを採用しました。

結局以下のようなスクリプトになりました。

# /bin/bash

if [ ! $# -eq 0 ];then # 引数があればリダイレクト
    exec 1>>$1
fi

cat <<EOS
1 foo
2 bar
3 baz
EOS

これを

$ ./spit.sh hoge.txt

で呼べばhoge.txtに書きこまれ、引数を与えずに単に

$ ./spit.sh 

とすれば標準出力に出力される。