シェルスクリプトで出力先がターミナルかどうかを判定する

先ほどの記事 でエスケープシーケンスまわりについて調べている時に、
「出力先がターミナル(tty)の場合」と「出力先がファイル、その他の場合」でエスケープシーケンスを出し分けする方法が気になりました。

たとえば、ls コマンドでは

$ ls --color=auto

と実行すると、ターミナルへの出力の場合にはエスケープシーケンスによって色付きで表示されますが、

$ ls --color=auto > foo

$ ls --color=auto | less

のようにファイルや別コマンドへの入力にした場合にはエスケープシーケンスが出力されません。

これと同じ動作をシェルスクリプトで実現しようとした場合、test コマンドの -t を使います。

  • t 1 で標準出力がターミナルかどうかを調べることができます。
if [ -t 1 ]; then
    printf "^[[31mhello world^[[0m\n"
else
    printf "hello world\n"
fi

これで出力先に応じて内容を調整できそうですね :-)

ちなみにシステムコールでは isatty(1) C言語ではライブラリ関数 isatty(3) を使うようです。
訂正 12/18: isatty のカテゴリをおもいっきり勘違いしていました。@flyingfoozy さん、指摘ありがとうございます。